01Name the six parts to find in every problem statement.
Input, output, rules, examples, limits and edge cases.
02In Second Largest, why did starting second at -1 fail?
With all values negative, -1 was bigger than every real value, so nothing ever replaced it.
03Which shape of code is O(log n)?
Code that halves the work at each step, such as binary search.
On LeetCode and on the A2Z sheet, the limits sit at the bottom of the problem, in small type. Most beginners skip them.
They are the biggest hint on the page. The limits tell you how fast the answer must be, before you have a single idea.
From n to the Big O you need
In the last lesson you found the limits in a statement. In this lesson you use them. The method has three steps:
- Find the largest n in the limits.
- Look up the slowest Big O that still fits in about 10⁸ steps.
- Think only about ideas with that Big O or faster.
The lookup table:
| Largest n | Slowest Big O that fits | Steps at the limit | Ideas with that cost |
|---|---|---|---|
| 10 | O(n!) | 10! ≈ 3.6 × 10⁶ | try every order |
| 20 | O(2ⁿ × n) | about 2 × 10⁷ | try every subset |
| 500 | O(n³) | 1.25 × 10⁸ | three nested loops |
| 5,000 | O(n²) | 2.5 × 10⁷ | two nested loops |
| 10⁵ to 10⁶ | O(n log n) | about 2 × 10⁷ | sort, binary search, heap |
| 10⁸ | O(n) | 10⁸ | one pass |
| 10⁹ to 10¹⁸ | O(log n) or O(1) | about 60 | binary search, a formula |
Read it from the left. Find your n, and the row tells you how much work you are allowed.
Small n is a hint, not a gift
Compare the same four answers at two sizes:
- O(n log n)86fits
- O(n²)400fits
- O(2ⁿ)10⁶fits
- O(n!)2.4 × 10¹⁸too slow
The line marks 10⁸ steps. Aim for O(2ⁿ) or faster.
- O(n log n)1.7 × 10⁶fits
- O(n²)10¹⁰too slow
- O(2ⁿ)over 10³⁰too slow
- O(n!)over 10³⁰too slow
The line marks 10⁸ steps. Aim for O(n log n) or faster.
At n = 20, an exponential answer is about a million steps. The problem setter picked a tiny n on purpose. When n is 20 or less, the intended answer usually tries every subset.
At n = 100,000, the same idea would never finish. Even n² is 10¹⁰ steps.
When n is huge, you cannot even loop
- O(1)1fits
- O(log n)30fits
- O(n)10⁹tight
The line marks 10⁸ steps. Aim for O(log n) or faster.
The bar says "tight" for O(n). That means about 10⁹ steps, roughly 10 seconds at 10⁸ per second. Against a 1 second limit, treat it as too slow.
So when n reaches 10⁹, look for:
- a formula: the sum 1 + 2 + ... + n is n × (n + 1) / 2, one step;
- a binary search over the answer: about 30 halvings for 10⁹.
When numbers get too big
The limits also give the range of each value, such as -10⁹ ≤ nums[i] ≤ 10⁹. That range tells you whether your sums and products still fit in a number.
Each language has its own limit:
- Java: an
intends at 2³¹ − 1 = 2,147,483,647, about 2.1 × 10⁹. Past that, it . Alonggoes to about 9.2 × 10¹⁸. - Python: an
inthas no limit. It grows as large as the value needs, so it never overflows. - TypeScript: a
numberholds every integer exactly up to , about 9 × 10¹⁵. Past that, it rounds the last digits.
Java and TypeScript give a wrong answer at that point. Neither one warns you.
Which results each type holds exactly:
| What you compute | Largest size | Java int | Java long | TS number |
|---|---|---|---|---|
| one value | 10⁹ | yes | yes | yes |
| sum of 10⁵ values up to 10⁹ | 10¹⁴ | no | yes | yes |
| sum 1 to n, n = 10⁹ | 5 × 10¹⁷ | no | yes | no |
| product of two values up to 10⁹ | 10¹⁸ | no | yes | no |
A Python int is exact in every row.
Here is the silent error, and the fix:
int a = 999_999_999;
System.out.println(a * a % 1_000_000_007); // 808348673: wrong
System.out.println((long) a * a % 1_000_000_007); // 64: rightThe product a * a is about 10¹⁸. Each language handles it differently:
- In Java, two
ints multiply as anint, so the product overflows before%runs. Cast one side tolongfirst:(long) a * a. - In Java,
long c = a * a;is still wrong. The product overflows as anint, and only then becomes along. - In Python, the product is exact. Very large ints cost a little more time, but they are never wrong.
- In TypeScript, the product is above the safe limit, so its last digits are already wrong. A stores any integer exactly. It is slower, and
1n + 1throws a TypeError: you cannot mix it with plain numbers.
Use long in Java when a value can pass 2.1 × 10⁹. Use BigInt in TypeScript only when it can pass 9 × 10¹⁵.
Two more signals from the same line:
- "Return the answer modulo 10⁹ + 7". The real answer is huge. Take
%after every step, not once at the end. - Sums of many values. 10⁵ values up to 10⁹ add up to 10¹⁴. In Java, keep that sum in a
long, as the solutions on the sheet do.
Memory has a limit too
Many judges allow 256 MB. A Java long and a TypeScript number take 8 bytes each, and a Java int takes 4.
- An array of 10⁶ numbers is about 8 MB: fine.
- An n × n table with n = 10⁴ is 10⁸ cells, about 800 MB: too much.
In Python, each list slot points to an int object, so a number costs about 36 bytes. A list of 10⁶ ints is about 36 MB. Still fine, but the n × n table is far out of reach.
So O(n) extra memory almost always fits. O(n²) memory only fits for n up to a few thousand.
Read the limits first: Koko Eating Bananas
Here is a real problem from the sheet. Read the limits before you think about a solution.
At 5 per hour the piles take 2 + 3 + 2 + 1 = 8 hours.
- 1 ≤ n ≤ 10⁴
- n ≤ h ≤ 10⁹
- 1 ≤ nums[i] ≤ 10⁹
Which pattern? Decide first, then open.
“smallest k that works”if k works, every bigger k works too: binary search on k
“nums[i] up to 10⁹”k can be anything from 1 to 10⁹, so you cannot try them all
pattern: Search on answer
Now read the limits, one at a time:
- n ≤ 10⁴. Even O(n²) fits. The number of piles is not the problem.
- nums[i] ≤ 10⁹. The speed k can be any value from 1 to 10⁹. That range is the real input size.
- Checking one speed means adding up the hours for every pile: O(n).
- Trying every speed costs 10⁹ × 10⁴ = 10¹³ steps. Far too slow.
- A faster speed never needs more hours. So binary search the speed: about 30 checks instead of 10⁹.
- Overflow check. At speed 1, the hours can reach 10⁴ × 10⁹ = 10¹³. That passes a Java
int, so count the hours in along. A Python int and a TypeScript number hold it exactly.
| Idea | Steps | Fits 10⁸? |
|---|---|---|
| try every speed | 10⁹ × 10⁴ = 10¹³ | no |
| binary search the speed | 30 × 10⁴ = 3 × 10⁵ | yes |
You picked the approach without writing any code. The binary search on answers chapter writes it.
Limits are pattern signals
In the last lesson, words in the statement pointed to patterns. The limits point too. Put the two together and most problems narrow to one or two ideas.
| The limits say | Try first |
|---|---|
| n ≤ 10 | every order (permutations) |
| n ≤ 20 | every subset, backtracking, bitmasks |
| n ≤ 500 | three loops, dynamic programming on ranges |
| n ≤ 5,000 | two loops, a 2D dynamic programming table |
| n up to 10⁵ or 10⁶ | sort, binary search, hash map, sliding window, heap |
| the input is sorted | binary search, two pointers |
| n or values up to 10⁹ or more | binary search on the answer, a formula |
| "modulo 10⁹ + 7" | a counting problem, often dynamic programming |
| values in a small range, such as 0 to 100 | a counting array in place of a sort |
The habit: limits first, then ideas. It takes ten seconds, and it removes most wrong roads before you walk them.
- 01
Read the limits first. The largest n sets the slowest Big O you can afford, at about 10⁸ steps per second.
- 02
n ≤ 20 hints at trying every subset. n up to 10⁵ needs O(n log n). n up to 10⁹ means no loop over n.
- 03
Know your limit: a Java int overflows past about 2.1 × 10⁹ (use long), a TypeScript number is exact to about 9 × 10¹⁵ (use BigInt), and a Python int never overflows.
- 04
O(n) extra memory almost always fits. O(n²) memory fits only for n up to a few thousand.
Read more
- Time complexity in the USACO Guide, with its own table of input sizes and the Big O each allows
- Number.MAX_SAFE_INTEGER on MDN
- BigInt on MDN, with what you can and cannot mix
- Koko eating bananas on takeUforward, to read the limits yourself
Next: the language toolbox. Pick the lesson for the language you code in, Java, Python or TypeScript, and learn what each operation costs.