04

Fast I/O, Judges & Debugging

Read input fast, understand what the judge is really telling you, and find your bug before anyone else does.

beginner~50 min3 simulations

▶ guided lesson⚡ 1-minute summary↻ 14 recall cards

before this: Java Arrays & Strings

01 · why it exists

Why this exists, and the weight it carries

since1969–72

Standard input and output

Ken Thompson, Dennis Ritchie and Doug McIlroy at Bell Labs (Unix)

Early Unix gave every program two ready-made files: standard input and standard output (file descriptors 0 and 1). The shell's < and > swapped them for files, so a program never needed to know where its data came from. Pipes appeared in 1972 at Doug McIlroy's suggestion, chaining one program's output into the next one's input. Online judges use exactly this: the test file becomes your stdin, and your stdout becomes a file they compare.

the problem it solvedPrograms could be combined and tested without changing their code — just by redirecting where input comes from and where output goes.

its jobs today

  • Online judges feed each test file to your stdin and capture your stdout for comparison.
  • Shell pipelines and CI scripts chain tools (sort, grep, diff) through stdin and stdout.

the weight it carries

Illustrative OA problem: 30 hidden test files, each with up to 10⁵ numbers in and 10⁵ lines out. Your program is started 30 times and every byte passes through stdin and stdout — a slow reader is paid for 30 times.

without it

Every program would need to know file names, and a judge couldn't run any submission the same way.

when · why · how

when
Stdin (OA) mode: the template gives you an empty main.
why
The judge only sees what you print — nothing else exists for it, so the exact format matters.
how
Read System.in through a BufferedReader; write to System.out through a PrintWriter or one StringBuilder, and flush.

02 · plain english

The idea in 30 seconds

On LeetCode a hidden driver calls your method. In many online assessments there is no driver: you read the input from stdin yourself and print the answer to stdout.

Either way a judge runs your code on hidden tests with a time limit and answers in one word: AC, WA, TLE, RE or MLE.

This chapter teaches you to read and print fast, decode those words, and catch your own bug before the judge — or the interviewer — does.

picture this

A judge is like booking an IRCTC Tatkal ticket: the form must be exactly right, and it must arrive before the window closes. A perfect form submitted late still gets nothing — that's a TLE.

03 · remember

What you must know

  • Two judging styles: LeetCode calls your method on class Solution. Stdin (OA) mode runs your main, feeds the test on System.in, and compares what you print.
  • Fast input: BufferedReader + StringTokenizer (the FastReader template). Scanner is fine for small inputs, but was about 4× slower at 10⁶ numbers in our measurement.
  • Fast output: collect lines in a StringBuilder or PrintWriter and write once — and always flush(). println per line flushes every single time.
  • Budget first: ~10⁸ simple steps per second is the rule of thumb. Read n in the constraints and pick the complexity before you code.
  • Verdicts are diagnoses: WA = wrong output, TLE = too slow, RE = crashed, MLE = too much memory, CE = didn't compile.
  • Exceptions travel up the call stack to the nearest matching catch; every frame in between is abandoned. The stack trace is a map to your bug.
  • Debug in this order: shrink the failing input → dry-run it → print to System.err or set a breakpoint → assert your invariants (java -ea).
  • Test before the judge does: the samples, then edge cases you choose on purpose, then a stress test against a brute force.

04 · see it

Play with it in 3D

Press Space to play, ←/→ to step, drag to move, ? for all shortcuts. Try your own input.

sim

How a judge runs one test

Try the submissions `off-by-one`, `crash`, `no-flush` and `slow` to see where each verdict comes from.

loading simulation…
sim

An exception unwinding the call stack

A bad token deep inside `parseRow` throws. Frames without a matching `catch` are discarded until `total` catches it.

loading simulation…
sim

Scanner vs BufferedReader, println vs one write — measured

Real timings from one desktop (JDK 26, median of 3 runs). Set your own time limit and see which bars break it.

loading simulation…

05 · cost

Time & space, explained

Reading and printing n items in Java
TimeMeasured at n = 10⁶why
Scanner.nextInt() × nO(n)530 msRegex-based token matching through a 1,024-char buffer: a big constant factor.
BufferedReader + StringTokenizer + parseIntO(n)140 msPlain character scanning through an 8,192-char buffer.
StreamTokenizerO(n)217 msFast, but parses every number as a double — exact for ints, not for longs above 2⁵³.
System.out.println() × nO(n)2,478 msSystem.out flushes on every println: one write to the OS per line.
PrintWriter, flushed onceO(n)87 msLines collect in a buffer and leave in a few large writes.
StringBuilder, printed onceO(n)48 msOne string, one write.
What usually fits in a 1-second limit (rule of thumb: ~10⁸ simple steps per second)
Largest n that usually fitswhy
O(n!)n ≤ 1010! ≈ 3.6 × 10⁶ orders, each needing more work.
O(2ⁿ)n ≤ 202²⁰ ≈ 10⁶ subsets, each needing more work.
O(n³)n ≤ 500500³ = 1.25 × 10⁸.
O(n²)n ≤ 5,0005,000² = 2.5 × 10⁷; at 10⁵ it would be 10¹⁰ — hopeless.
O(n log n) or O(n)n ≤ 10⁶10⁶ × 20 = 2 × 10⁷.
O(log n) or O(1)any nlog₂ 10¹⁸ ≈ 60 steps.
Verdicts: what the judge is telling you
MeansUsual cause in Javawhy
AC — Acceptedevery test passed—Output matched on every hidden test, within the limits.
WA — Wrong Answerran fine, output differslogic bug, `int` overflow, wrong format, forgot `flush()`The program finished normally; the checker compared and disagreed.
TLE — Time Limit Exceededdidn't finish in timewrong complexity, infinite loop, Scanner/println on huge I/OThe judge stops the program at the limit, so the output is never checked.
RE — Runtime Errorcrashedindex out of bounds, null, bad parse, StackOverflowErrorAn uncaught exception or a non-zero exit code.
MLE — Memory Limit Exceededused too much memory`new int[n][n]` for big n, boxed collectionsSome judges report this as a runtime error instead.
CE — Compile Errordidn't compilewrong class name for the platform, missing importNothing ran; read the first compiler message.

06 · java

Raw vs Collections Framework

Online-assessment input with Scanner

javaread n, then n numbersjava.io.* · java.nio.charset.StandardCharsets · java.util.*
class Main {    public static void main(String[] args) {        Scanner in = new Scanner(System.in);        int n = in.nextInt();                  // first token: how many numbers follow        long sum = 0;                          // n values up to 10^9 overflow int: use long        for (int i = 0; i < n; i++) sum += in.nextInt(); // any spaces or newlines between them        System.out.println(sum);    }}
  • Scanner doesn't care how numbers are split across lines — nextInt() skips any spaces and newlines.
  • It is simple and correct, and fine up to roughly 10⁴–10⁵ tokens. For bigger inputs, use the fast template below.
  • Sum many values in a long: 10⁵ values up to 10⁹ reach 10¹⁴, far past int's 2,147,483,647.

The nextInt + nextLine trap

javawhy name comes back emptyjava.io.* · java.nio.charset.StandardCharsets · java.util.*
class LineTrap {    static String readAgeThenName(String input) {        Scanner in = new Scanner(input);        int age = in.nextInt();                // reads "21" but leaves the '\n' behind        String rest = in.nextLine();           // returns "" — the rest of the age line!        String name = in.nextLine();           // only now the real next line        return age + "|" + rest + "|" + name;    }     static String readAgeThenNameFixed(String input) {        Scanner in = new Scanner(input);        int age = Integer.parseInt(in.nextLine().trim()); // read whole lines, parse yourself        String name = in.nextLine();        return age + "|" + name;    }}
  • nextInt() stops right after the digits; the line break is still waiting. The next nextLine() returns the rest of that line: "".
  • Simplest fix: read whole lines with nextLine() (or readLine()) and parse them yourself with Integer.parseInt(line.trim()).

The fast template: BufferedReader + StringTokenizer + PrintWriter

javalearn this one by heartjava.io.* · java.nio.charset.StandardCharsets · java.util.*
class Main {    public static void main(String[] args) throws IOException {        FastReader in = new FastReader(System.in);        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));        int n = in.nextInt();        long sum = 0;        for (int i = 0; i < n; i++) sum += in.nextInt();        out.println(sum);        out.flush();                       // forget this and the judge sees NOTHING    }     /** Reads whitespace-separated tokens, whatever the line layout. */    static class FastReader {        private final BufferedReader br;        private StringTokenizer st;         FastReader(InputStream stream) {            br = new BufferedReader(new InputStreamReader(stream), 1 << 16); // 64 KB buffer        }         String next() throws IOException {            while (st == null || !st.hasMoreTokens()) {                String line = br.readLine();                if (line == null) return null;        // end of input                st = new StringTokenizer(line);       // splits on spaces and tabs            }            return st.nextToken();        }         int nextInt() throws IOException {            return Integer.parseInt(next());        }         long nextLong() throws IOException {            return Long.parseLong(next());        }    }}
  • FastReader.next() refills from the next line whenever the current one runs out, so it doesn't care about line layout — numbers may be on one line or many.
  • StringTokenizer is called a legacy class in its docs, but it's still a fast, simple way to split a line on whitespace. line.trim().split("\\s+") also works (it runs a regex).
  • out.flush() at the end is not optional. Without it, the answer stays in the buffer and the judge sees empty output.
  • Need longs? in.nextLong(). End of input? next() returns null.

Printing many lines

javacollect, then print oncejava.io.* · java.nio.charset.StandardCharsets · java.util.*
class ManyLines {    static void printSquares(int n) {        StringBuilder sb = new StringBuilder();        for (int i = 1; i <= n; i++) sb.append((long) i * i).append('\n'); // collect...        System.out.print(sb);                                              // ...print once    }}
  • System.out flushes on every println, so 10⁶ printlns mean 10⁶ separate writes. In our measurement: 2,478 ms vs 48 ms for one StringBuilder.
  • Append '\n' yourself. Judges ignore trailing spaces and the final newline, but not missing newlines between answers.

Reading until the input ends (EOF)

javano count givenjava.io.* · java.nio.charset.StandardCharsets · java.util.StringTokenizer
class Main {    public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        StringBuilder out = new StringBuilder();        String line;        while ((line = br.readLine()) != null) {   // null means: no more input (EOF)            line = line.trim();            if (line.isEmpty()) continue;          // tolerate blank lines            StringTokenizer st = new StringTokenizer(line);            long a = Long.parseLong(st.nextToken());            long b = Long.parseLong(st.nextToken());            out.append(a + b).append('\n');        // one answer per input line        }        System.out.print(out);                     // one big write at the end    }}
  • readLine() returns null when there is no more input. That's your loop condition.
  • With Scanner the same idea is while (in.hasNextInt()) { … }.
  • Testing locally in a terminal? End the input with Ctrl+Z then Enter (Windows) or Ctrl+D (Linux/macOS).

How a judge runs your code

javafeed → run → capture → comparejava.io.* · java.nio.charset.StandardCharsets · java.util.*
class MiniJudge {    interface Program {        void run() throws Exception;    }     static String judge(String input, String expected, Program program, long limitMs) {        InputStream realIn = System.in;        PrintStream realOut = System.out;        ByteArrayOutputStream captured = new ByteArrayOutputStream();        System.setIn(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8))); // test input becomes stdin        System.setOut(new PrintStream(captured, true, StandardCharsets.UTF_8));         // stdout goes into a buffer        long start = System.nanoTime();        try {            program.run();                                       // your main runs here        } catch (Throwable crash) {            return "RE: " + crash.getClass().getSimpleName();    // it crashed        } finally {            System.setIn(realIn);            System.setOut(realOut);        }        long ms = (System.nanoTime() - start) / 1_000_000;        if (ms > limitMs) return "TLE";              // a real judge kills you AT the limit        String got = normalize(captured.toString(StandardCharsets.UTF_8));        return got.equals(normalize(expected)) ? "AC" : "WA";    }     /** Ignores \r, spaces at line ends and blank lines at the very end — nothing else. */    static String normalize(String text) {        StringBuilder sb = new StringBuilder();        for (String line : text.replace("\r", "").split("\n")) sb.append(line.stripTrailing()).append('\n');        return sb.toString().stripTrailing();    }}
  • LeetCode style: a hidden driver builds the arguments, calls your Solution method and compares the return value. Stdin style: the judge does what this toy does — test file on System.in, your main, captured System.out, compare.
  • This site's stdin-mode judges work the same way: your Main.main gets the test text on System.in, and spaces at line ends and blank lines at the end are ignored. Tests include everything on one line, extra spaces and Windows \r\n endings — so read tokens, never assume a line layout.
  • Each test is judged separately and the first failure decides the verdict. Passing the samples proves very little.
  • A real judge kills your program at the time limit; this toy only measures afterwards, to keep the idea simple.

Four submissions, four verdicts

javaAC, WA, RE and a silent WAjava.io.* · java.nio.charset.StandardCharsets · java.util.*
class Submissions {    /** AC: read n, then n numbers on one line; print their sum. */    static void correct() throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        StringTokenizer st = new StringTokenizer(br.readLine());        long sum = 0;        for (int i = 0; i < n; i++) sum += Long.parseLong(st.nextToken());        System.out.println(sum);    }     /** WA: the loop stops one number early. */    static void offByOne() throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        StringTokenizer st = new StringTokenizer(br.readLine());        long sum = 0;        for (int i = 0; i < n - 1; i++) sum += Long.parseLong(st.nextToken());        System.out.println(sum);    }     /** RE: parses the whole line "3 9 4" as ONE number -> NumberFormatException. */    static void crash() throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        br.readLine();                                   // skip n        System.out.println(Long.parseLong(br.readLine())); // the line has spaces in it    }     /** WA with the right logic: the PrintWriter is never flushed, so stdout stays empty. */    static void noFlush() throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));        int n = Integer.parseInt(br.readLine().trim());        StringTokenizer st = new StringTokenizer(br.readLine());        long sum = 0;        for (int i = 0; i < n; i++) sum += Long.parseLong(st.nextToken());        out.println(sum);                                // waits in the buffer... then main ends    }}
  • offByOne runs fine and prints a number — that's why WA hurts: nothing crashes to tell you.
  • crash passes when the line holds one number and fails when it holds several. The samples might never show it.
  • noFlush has perfect logic and still gets WA. The judge only sees bytes that reached stdout.

The exceptions you will actually hit

javaone line each, and what it usually meansjava.util.*
class Bugs {    static int lastElement(int[] a) {        return a[a.length];                  // off by one -> ArrayIndexOutOfBoundsException    }     static char firstChar(String s) {        return s.charAt(0);                  // s is null -> NullPointerException    }                                        // ("" -> StringIndexOutOfBoundsException)     static int parse(String token) {        return Integer.parseInt(token);      // "12a", "", " 7" -> NumberFormatException    }     static int average(int sum, int count) {        return sum / count;                  // count == 0 -> ArithmeticException: / by zero    }     static void removeEvens(List<Integer> list) {        for (Integer x : list) {            if (x % 2 == 0) list.remove(x);  // changing a list while for-each walks it        }                                    // -> ConcurrentModificationException    }     static int depth(int n) {        return 1 + depth(n + 1);             // no base case -> StackOverflowError    }     static long[] hugeTable() {        return new long[Integer.MAX_VALUE];  // ~16 GB, far past any judge's limit -> OutOfMemoryError    }}
  • ArrayIndexOutOfBoundsException / StringIndexOutOfBoundsException: an off-by-one or an empty input — check i < n and guard n == 0.
  • NullPointerException: an object you never created (a null array slot, a missing map key unboxed into int). Since JDK 15 the message names exactly what was null.
  • NumberFormatException: parsing a token that isn't a clean integer — spaces, empty strings, decimals, or a number bigger than int.
  • ArithmeticException: / by zero: integer division or % by 0. (Double division gives Infinity instead.)
  • ConcurrentModificationException: you changed a list while a for-each loop walked it. Use removeIf or an Iterator.
  • StackOverflowError / OutOfMemoryError are Errors, not Exceptions: recursion too deep, or a table too big (new int[n][n] with n = 10⁵ is 40 GB).

How an exception travels up the stack

javathrow deep, catch highjava.util.*
class Unwinding {    static int total(String[] rows) {        try {            return sumRows(rows);        } catch (NumberFormatException e) {            return -1;                                   // the exception lands here        }    }     static int sumRows(String[] rows) {                  // no catch here: it just passes through        int sum = 0;        for (String row : rows) sum += parseRow(row);        return sum;    }     static int parseRow(String row) {                    // no catch here either        int s = 0;        for (String token : row.split(",")) {            s += Integer.parseInt(token.trim());         // "7x" -> throws        }        return s;    }}
  • When parseInt throws, Java looks for a matching catch in the current method, then its caller, then its caller's caller. Methods without one simply end.
  • The stack trace prints that same chain, newest call first. Find the first line that names your code — the bug is usually there or one line above.
  • Catch only what you can handle (bad user input, for example). In DSA practice, let bugs crash loudly — the trace is a gift.

assert and print debugging

javacheck assumptions, print a dry-run tablejava.util.*
class Tools {    static int maxOf(int[] a) {        assert a.length > 0 : "maxOf needs at least one element"; // checked only with java -ea        int best = a[0];        for (int i = 1; i < a.length; i++) {            // System.err.println("i=" + i + " a[i]=" + a[i] + " best=" + best); // print debugging            if (a[i] > best) best = a[i];        }        return best;    }     static String trace(int[] a) {        StringBuilder table = new StringBuilder("i a[i] best\n");   // a dry-run table, printed        int best = a[0];        for (int i = 1; i < a.length; i++) {            if (a[i] > best) best = a[i];            table.append(i).append(' ').append(a[i]).append(' ').append(best).append('\n');        }        return table.toString();    }}
  • assert cond : message; runs only when the JVM starts with -ea (java -ea Main). Off by default — so never put needed work inside an assert.
  • Print debugging goes to System.err, so it doesn't mix with the answer on stdout. Delete it before submitting; printing is slow.
  • trace builds the dry-run table from the Mindset chapter for you: one row per iteration, one column per variable.
  • In an IDE, a breakpoint on the suspicious line plus the variables panel does the same job without editing code.

Your own tests: samples and edge cases

javaa ten-line test harnessjava.util.*
class OwnTests {    static int failures = 0;     static void expect(String name, int got, int want) {        if (got != want) {            failures++;            System.err.println("FAIL " + name + ": got " + got + ", want " + want);        }    }     static int runAll() {        failures = 0;        expect("the example", Tools.maxOf(new int[] {3, 9, 2}), 9);        expect("single element", Tools.maxOf(new int[] {5}), 5);        expect("all negative", Tools.maxOf(new int[] {-4, -2, -8}), -2);        expect("max at the end", Tools.maxOf(new int[] {1, 2, 3}), 3);        expect("all equal", Tools.maxOf(new int[] {7, 7, 7}), 7);        expect("int limits", Tools.maxOf(new int[] {Integer.MIN_VALUE, Integer.MAX_VALUE}), Integer.MAX_VALUE);        return failures;    }}
  • Choose edge cases on purpose: one element, all equal, all negative, the answer at either end, int limits.
  • For random tests against a brute force, reuse the stress-test block in the Mindset chapter: small random inputs, a fixed seed, stop at the first mismatch.

Shrink a failing input

javamake the bug small enough to seejava.util.*
class Shrink {    interface Bug {        boolean showsOn(int[] input);    }     /** Drops one element at a time while the bug still shows: a big failing input becomes a tiny one. */    static int[] shrink(int[] failing, Bug bug) {        int[] current = failing.clone();        boolean smaller = true;        while (smaller) {            smaller = false;            for (int i = 0; i < current.length && !smaller; i++) {                int[] candidate = without(current, i);                if (bug.showsOn(candidate)) {    // still broken without element i?                    current = candidate;         // keep the smaller input and start again                    smaller = true;                }            }        }        return current;    }     static int[] without(int[] a, int skip) {        int[] b = new int[a.length - 1];        for (int i = 0, j = 0; i < a.length; i++) if (i != skip) b[j++] = a[i];        return b;    }}
  • Remove one element at a time; keep the removal if the bug still shows. Repeat until nothing more can go.
  • Our example: 8 negative numbers shrink to [-6], and the bug — best starts at 0 — is obvious at that size.
  • By hand works too: delete half the input, rerun, repeat. Small failing cases explain themselves.
Java API you will actually use
calldoescost
new Scanner(System.in) · nextInt() / nextLong() / next() / nextLine()Simple token and line readingO(token), large constant
new BufferedReader(new InputStreamReader(System.in)) · readLine()One line at a time; null at end of inputO(line)
new StringTokenizer(line) · nextToken() / hasMoreTokens()Split a line on whitespace, fastO(token)
Integer.parseInt(s) / Long.parseLong(s)Text → number; throws NumberFormatExceptionO(digits)
new PrintWriter(new BufferedOutputStream(System.out)) · flush()Buffered output — flush once at the endO(total output)
StringBuilder + System.out.print(sb)Collect every line, print onceO(total output)
System.err.println(x)Debug output that stays out of stdoutslow — delete before submitting
assert cond : "message";Checked only with java -eaO(cost of cond)
e.getMessage() / e.printStackTrace()What went wrong, and where—
list.removeIf(x -> …) / iterator.remove()Remove while iterating, safelyO(n)

Small input, quick to write

→ Scanner

The simplest API; fast enough up to about 10⁴–10⁵ tokens.

Big input (10⁵–10⁶ tokens)

→ BufferedReader + StringTokenizer (FastReader)

About 4× faster than Scanner at 10⁶ ints in our measurement.

Many output lines

→ StringBuilder or PrintWriter, written once

println per line was ~28–52× slower at 10⁶ lines in our measurement.

Input ends without a count

→ while ((line = br.readLine()) != null)

readLine returns null at end of input.

Check an assumption while practising

→ assert + java -ea

Loud the moment it breaks; skipped when disabled.

Find the bug in a big failing input

→ Shrink it, then dry-run the small case

A 3-number failure is readable; a 10⁵-number one isn't.

07 · recognise

Spot the pattern

"Input: the first line has n, the next line has n integers"

Stdin mode: FastReader template in, StringBuilder or PrintWriter out

"Read until the end of input" / no count given

readLine() loop until it returns null

n up to 10⁵–10⁶ in the constraints

Need O(n log n) or better — and fast I/O in stdin mode

TLE, but your algorithm is O(n)

Suspect Scanner or println-per-line before the algorithm

Samples pass, WA on hidden tests

Edge cases and overflow: write them as your own tests

RE on a hidden test

Index bounds, null, parse of a bad token, recursion depth

Your output looks right but the verdict is WA

Format: missing newline between answers, extra text, forgot flush

08 · traps & tricks

Mistakes to avoid, tricks to use

traps

  • Forgetting out.flush() (or out.close()) with a PrintWriter: empty output, WA with correct logic.
  • nextInt() followed by nextLine() returns "" — the rest of the number's line.
  • Scanner plus println-per-line on 10⁶ items: TLE with a perfect algorithm.
  • Summing 10⁵ values up to 10⁹ in an int: it overflows silently. Use long.
  • Debug prints left on stdout: the checker compares them too. Use System.err and delete them.
  • Removing from a list inside a for-each loop → ConcurrentModificationException. Use removeIf or an Iterator.
  • Recursion about 10⁵ calls deep can throw StackOverflowError on a judge. Use a loop or an explicit stack.
  • catch (Exception e) {} that swallows everything hides the real bug — and doesn't even catch StackOverflowError.
  • Relying on assert for checks your answer needs: without -ea it never runs.

tricks

  • Type the FastReader template from memory once a week until it's automatic. In an OA, every minute counts.
  • Read a stack trace from the top: exception and message first, then the first line that names your class — start there.
  • Shrink before you stare: delete half the input, rerun, repeat.
  • Before submitting: run the samples, then 3 edge cases — the smallest input, all values equal, extremes like 10⁹ and negatives.
  • After two wrong answers on the same problem, stop resubmitting and dry-run on paper. Repeated WAs predict more WAs.
  • Chalo, make it a ritual: samples → edge cases → stress test → submit. Calm and repeatable beats lucky.

09 · why & how

Questions you might be too shy to ask

LeetCode never asks me to read input. Why learn this?

Because LeetCode's driver does it for you. Many online assessments hand you raw stdin and an empty main instead. If you can't read input fast and correctly, you lose the round before the algorithm even matters.

How does a stdin-style online assessment judge my code?

Like the mini judge in this chapter: your main gets the test text on System.in, and what you print is compared with the expected output. Many judges forgive spaces at line ends and blank lines at the end, but check the platform's rules. Tests may put everything on one line, add extra spaces or use Windows line endings, so read tokens, not lines, and you're safe.

In stdin mode, what must my class be called?

Whatever the platform's starter code says, so read it before you type. On this site, and on many stdin judges, it is public class Main with a public static void main(String[] args). Rename it to Solution or MyCode and you can get a Compile Error even though the logic is perfect.

Why does the template say main(...) throws IOException? Do I need a try/catch?

readLine() can fail with an IOException, a checked exception: Java forces you to either catch it or declare it. Adding throws IOException to main declares it and keeps the code short. In OA code that is normal and fine; no try/catch needed.

I ran my stdin program locally and it just sits there, doing nothing. Is it stuck?

No, it is waiting for you. readLine() and nextInt() pause until input arrives on stdin. Type or paste the sample input and press Enter. If your loop reads until the end of input, finish with Ctrl+Z then Enter (Windows) or Ctrl+D (Linux/macOS).

Why is Scanner slow if it's in the standard library?

Its job is flexibility: its docs say it parses using regular expressions, and it reads through a 1,024-char buffer. BufferedReader just scans characters through an 8,192-char buffer. Same O(n), but in one rough measurement on our machine Scanner was about 4× slower at 10⁶ numbers (the exact factor varies by setup).

Is one System.out.println(answer) slow too?

No. The cost is per call: one write to the OS each time. One answer, or a few hundred lines, is nothing. In one rough measurement on our machine, 10⁶ printlns took about 2.5 s (about 2.5 µs each); your numbers will differ with the machine, the OS and where the output goes. Switch to a StringBuilder or PrintWriter once you print tens of thousands of lines or more.

Does one missing space or newline really give Wrong Answer?

Between values, yes: 1 2 and 12 are different answers, and so are two answers on one line when the judge wants one per line. What most judges forgive is extra space at the end of a line and blank lines at the very end. So print exactly the separators the statement shows, and nothing else (no "Answer:" text).

My code compiled. What does Runtime Error mean?

Compiling only proves the syntax. RE means the program crashed while running — an uncaught exception (bad index, null, bad parse, stack overflow) or a non-zero exit. The judge stops there; your output isn't even compared.

Is "10⁸ operations per second" a real number?

It's a rule of thumb, not a law. Laaksonen's Competitive Programmer's Handbook says a modern computer does "some hundreds of millions of operations" per second; judges add overhead, and Java adds JVM start-up. Use it to estimate: if your count is well above 10⁸ for a 1-second limit, find a better algorithm.

I got TLE on LeetCode. Should I switch to fast I/O?

No. On LeetCode the hidden driver reads and prints for you, so your I/O choice is not the problem. TLE there almost always means the algorithm is too slow for n (say O(n²) at n = 10⁵), or a loop that never ends. Recount your steps against the constraints first.

Debugger or print statements?

Both are fine. In an IDE, a breakpoint plus the variables panel is fastest. On an online judge, print to System.err and remove it afterwards. In a live interview, a spoken dry-run table beats both.

The judge only says Wrong Answer. How do I find the failing case?

Make your own: the samples, then edge cases you pick on purpose, then a brute-force stress test on small random inputs (the Mindset chapter has one ready). When something fails, shrink it until the bug is obvious. Bas itna yaad rakho: a small failing input is worth more than an hour of staring.

Why doesn't catch (Exception e) catch StackOverflowError?

It's an Error, not an Exception. Both extend Throwable, but the JLS describes Error as problems ordinary programs aren't expected to recover from. In DSA it simply means: recursion too deep, or (OutOfMemoryError) a table too big.

10 · practice

Interview problems

Practise this chapter on these

Each problem has one home page in the course; these use this chapter's idea too. The note says what to look for.

  1. #387
    First Unique Character in a String
    Easyin Java Arrays & Strings

    Submit the O(n²) version once: its 50,000-char hidden test shows you a real TLE.

  2. #1480
    Running Sum of 1d Array
    Easyin Mindset

    Solve it, then rewrite it as a stdin program: read n and n numbers, print the running sums with one StringBuilder.

11 · revise

The whole chapter on one screen

8 cards, about a minute. Read them the night before an interview, or right after the chapter to lock it in.

  1. what it is

    A judge runs your program once per test: input file → stdin → your code → stdout → checker. It only sees what you print.

  2. use it when

    Stdin mode with 10⁵+ tokens → BufferedReader + StringTokenizer in, StringBuilder or PrintWriter out. Small input → Scanner is fine.

  3. template

    PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out)); … out.println(ans); out.flush();

  4. cost

    Rule of thumb: ~10⁸ simple steps per second. n = 10⁵: O(n²) = 10¹⁰ → TLE. O(n log n) ≈ 1.7 × 10⁶ → fine.

  5. trap

    PrintWriter without flush() prints nothing → WA. nextInt() then nextLine() returns "". Debug prints on stdout → WA.

  6. pro tip

    Verdicts are diagnoses: WA = output, TLE = complexity or slow I/O, RE = an exception, MLE = memory, CE = compile.

  7. trap

    AIOOBE = bad index · NPE = null · NumberFormat = bad parse · Arithmetic = / by zero · CME = edit in for-each · StackOverflow = deep recursion.

  8. pro tip

    Stuck on WA? Samples → edge cases → stress test vs brute force → shrink the failing input → dry-run it.

12 · recall

Flip, remember, repeat

card 1 / 14
recall

Your PrintWriter solution prints nothing on the judge. Why?

tap or Space to flip ↻

Question 1: Your PrintWriter solution prints nothing on the judge. Why?

13 · check yourself

Quick quiz

  1. Your PrintWriter solution prints nothing on the judge but the logic is right. What did you forget?

  2. Input "21\nPriya". After `int age = in.nextInt();`, what does `in.nextLine()` return?

  3. n ≤ 10⁵ and your solution is O(n²). With a 1-second limit, expect…

  4. Your code compiled and the verdict is RE. Which is NOT a likely cause?

  5. parseRow throws, total catches, and sumRows sits in between without a catch. What happens to sumRows?

  6. `assert x > 0;` with x = -5, run as plain `java Main`. What happens?