L01 · The LeetCode Game — How to Read a Problem
Constraints are not decoration. They are the interviewer quietly telling you which complexity class is acceptable, and therefore which algorithm to reach for.
🎯 Learn to read the constraints block first and convert it into a shortlist of acceptable complexity classes — before you even understand what the problem is asking.
Series: LeetCode — From Basics to Interview-Ready · Session 1 / 65 · Phase 0 · Foundations
What this session IS — reading the tiny print
Every LeetCode problem has three parts: a story, some examples, and — at the very bottom, in a block most people scroll past — the Constraints. It looks like this:
Constraints:
1 <= n <= 10^5
-10^9 <= nums[i] <= 10^9
Beginners read the story and start coding. Strong candidates read the constraints first. Here is why: the constraint on n is the problem setter quietly telling you which algorithms are allowed to pass, and therefore which one they intend you to find.
A computer does roughly 10^8 (a hundred million) simple operations per second in a judge's time limit. That single fact turns the size of n into a budget. If n is 100,000 and your algorithm does n^2 work, that is 10^10 operations — a hundred times over budget. It will time out. The constraint just told you: do not write two nested loops over n.
n <= 10^5 does not tell you the algorithm. It tells you the algorithm must be about n log n or faster — which prunes the choices down to a handful before you have understood the problem at all.The naive approach and why it is slow
Take "find two numbers in a list that add up to a target". The obvious approach: try every pair.
def two_sum_brute(nums, target):
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]
return []Two nested loops over n items is n^2 pairs. If the constraints say n <= 10^4, that is 10^8 — right at the edge, might pass. If they say n <= 10^5, that is 10^10 — dead. The same code is fine or fatal depending only on a number at the bottom of the page. That is why you read it first.
The table you must memorise
This is the whole session compressed into one lookup. Given the largest input size, here is the fastest complexity you are allowed to need:
Largest n | Rough op budget | Acceptable complexity | Typical technique |
|---|---|---|---|
| n ≤ 12 | tiny | O(n!) | permutations, brute backtracking |
| n ≤ 20 | tiny | O(2^n) | subsets, bitmask DP |
| n ≤ 500 | ~10^8 | O(n^3) | interval DP, Floyd–Warshall |
| n ≤ 5,000 | ~10^7 | O(n^2) | pairwise DP, quadratic scans |
| n ≤ 10^5 | ~10^8 | O(n log n) | sort, heap, binary search, two pointers |
| n ≤ 10^6 | ~10^8 | O(n) | single pass, hashing, sliding window |
| n ≥ 10^9 | huge | O(log n) or O(1) | binary search on the answer, math |
Read the row that matches the biggest number in the constraints. Everything to the right of your budget times out. Everything to the left is allowed but usually overkill.
- 1A judge allows roughly 10^8 primitive operations in its time limit.forced by · That is about one second of CPU work, and time limits are set around that.
- 2Your algorithm's running time is (operations per element) times (number of elements), expressed as a Big-O in n.forced by · Big-O counts how the work grows as n grows.
- 3If you plug the largest allowed n into your Big-O and exceed 10^8, the code times out.forced by · You have asked for more work than the budget allows.
- 4So the constraint on n rules out every complexity class above a threshold.forced by · Only the classes whose value at that n stays under 10^8 can pass.
- 5Each surviving complexity class maps to a small family of techniques.forced by · O(n log n) means sort/heap/binary-search; O(n) means one pass/hashing; O(log n) means binary search on the answer.
The template — a reading ritual
There is no code skeleton this session; the "template" is a fixed sequence you run on every problem before writing a line. Say it out loud.
The single most valuable sentence you can utter in an interview is step 2, said before you code:
"n is up to ten to the fifth, so I'm targeting n log n — checking all pairs is out."
It signals you cost things before writing them, which is most of what the interviewer is scoring.
- Bigger n pushes the fence LEFT (fewer techniques allowed).
- n <= 20 pushes it far right — exponential is invited, look for subsets/backtracking.
- n = 10^5 or 10^6 pushes it to n log n / n — think sort, hash, two pointers, sliding window.
- Always read the fence position BEFORE reading the story.
Memory technique — the powers-of-ten peg
You do not need to memorise the whole table if you memorise three anchor pegs and interpolate:
- "Twenty is exponential." n ≤ 20 → 2^n / n! are fine. Peg image: a tiny room where you can afford to try every arrangement.
- "Hundred-thousand is log-linear." n ≤ 10^5 → n log n. Peg image: a sorted filing cabinet — you sort once, then everything is fast.
- "Million is one pass." n ≤ 10^6 → O(n). Peg image: a conveyor belt you may touch each item exactly once.
Chant it as a rhythm: "twenty exponential, hundred-K log-linear, million one-pass." Three pegs, said as one phrase, recovers the whole table because everything else sits between them.
What interviewers actually ask
Reading constraints is not a problem type — it is the habit that sits under every problem. But interviewers deliberately encode signals in the numbers, and these classic problems reward reading them:
- Two Sum (1) · Amazon, Google, Meta (Easy) — probes: do you notice
nis large enough that the O(n^2) pair scan is a warm-up, not the answer. Follow-up: "what if the array were sorted?" (drops you into two-pointers, L07). - Best Time to Buy and Sell Stock (121) · Amazon, Microsoft (Easy) — probes:
n <= 10^5forbids the O(n^2) "try every buy/sell pair"; the constraint is the hint to find the one-pass running-min. Follow-up: "with multiple transactions?" - Search in Rotated Sorted Array (33) · Amazon, Microsoft, Meta (Medium) — probes: the problem says O(log n) is expected; that single line forces binary search over a linear scan. Follow-up: "with duplicates" (81).
- Subsets (78) · Amazon, Meta (Medium) — probes:
n <= 10(tiny) is the setter inviting an exponential 2^n enumeration; reading it tells you backtracking is intended, not feared. Follow-up: "with duplicates" (90). - Koko Eating Bananas (875) · Amazon, Meta (Medium) — probes: huge value range for the answer with small
nsignals binary search on the answer, not on the array. Follow-up: "minimise something else under a budget." - Median of Two Sorted Arrays (4) · Google, Amazon (Hard) — probes: the problem states O(log(m+n)); that constraint alone rules out merging and forces a partition binary search.
Worked example 1 — reading n to pick the tool
Problem in plain words: Given a list nums and a target, return the indices of two numbers that add to target. Constraints: 2 <= n <= 10^4, values fit in normal ints.
Brute force + cost. Try every pair (the code above). Cost: O(n^2). At n = 10^4 that is 10^8 — borderline, probably passes, but it is the warm-up, and you should say so.
The insight. The budget row for 10^4 allows O(n^2), but the value range and "find a complement" phrasing invite O(n) with a hash map: for each number, ask whether target - number was already seen.
def two_sum(nums, target):
seen = {} # value -> index we saw it at
for i, x in enumerate(nums): # one pass, O(n)
need = target - x # the complement that would complete the pair
if need in seen: # dict lookup is O(1) average
return [seen[need], i]
seen[x] = i # remember x for a future partner
return []Complexity. Time O(n) (one pass, O(1) lookups). Space O(n) for the map. We spent memory to buy time — the core trade of L05.
Follow-up they escalate to. "What if the array were already sorted — can you do it in O(1) extra space?" That drops the map for two converging pointers, which is exactly L07.
import random, time
nums = [random.randint(-10**9, 10**9) for _ in range(20000)]
target = nums[3] + nums[19999] # a real pair near the ends
t = time.time(); two_sum_brute(nums, target); print("brute", round(time.time()-t, 3), "s")
t = time.time(); two_sum(nums, target); print("hash ", round(time.time()-t, 3), "s")You should see the brute version an order of magnitude slower — that gap is the difference between "passes" and "time limit exceeded" as n grows.
Worked example 2 — a tiny n inviting exponential work
Problem in plain words: Return every subset of a list of up to 10 distinct numbers. Constraints: n <= 10.
Reading first. n <= 10 is a tiny number. From the table, that is deep in exponential territory: 2^n = 1024 subsets, trivial. The constraint is the setter saying "enumerate everything, do not be clever." Fearing the exponential here is the mistake.
def subsets(nums):
result = [[]] # start with the empty subset
for x in nums: # for each number...
# ...double the collection: every existing subset, plus a copy that includes x
result += [subset + [x] for subset in result]
return result
# subsets([1,2,3]) -> [[], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]]Complexity. There are 2^n subsets and we build each once: O(n · 2^n) time and output. At n = 10 that is about 10,000 — instant. The constraint guaranteed this would be fine before we wrote it.
Follow-up. "What if the list has duplicates and you must not repeat subsets?" → sort first, skip a value when it equals the previous one at the same depth (Subsets II, 90).
Worked example 3 — the answer's range, not n, sets the budget
Problem in plain words: Koko eats bananas from piles; she eats k bananas/hour from one pile. Find the smallest k that finishes all piles within h hours. Constraints: n <= 10^4 piles, each pile up to 10^9 bananas.
Reading first. n is small (10^4) but a pile can be 10^9. A linear scan of possible speeds k from 1 upward would be up to 10^9 tries — far over budget. The answer's range is huge and the "smallest k that satisfies a condition" phrasing is the tell: binary search on the answer.
def min_eating_speed(piles, h):
import math
def hours_at(speed): # hours needed if she eats `speed`/hr
return sum(math.ceil(p / speed) for p in piles)
lo, hi = 1, max(piles) # speed is between 1 and the biggest pile
while lo < hi: # binary search for the smallest feasible speed
mid = (lo + hi) // 2
if hours_at(mid) <= h: # mid is fast enough → try slower (fewer bananas/hr)
hi = mid
else: # too slow → must eat faster
lo = mid + 1
return lo # lo == hi == smallest feasible speedComplexity. O(n log(max pile)) — the log turns 10^9 candidate speeds into ~30 checks, each O(n). Comfortably under budget. Reading the value range, not just n, is what pointed here.
Follow-up. "Ship packages within D days (1011)" and "Split array largest sum (410)" are the same binary-search-on-answer shape.
Where this shows up in production
The constraint-reading instinct is the same one senior engineers use when sizing a system: before choosing a data structure they ask "how big does this get?" A lookup over a few dozen config keys can be a plain list scan; the same scan over millions of rows per request needs an index or a hash map. The habit — let the size choose the structure — is identical to reading n before choosing an algorithm. That is why interviewers value it: it is a small, honest proxy for how you will make real design decisions.
- Find the Constraints block first and read off the largest n.
- Recite the powers-of-ten pegs: twenty exponential, hundred-K log-linear, million one-pass.
- Convert a value of n into a target complexity out loud before coding.
- Spot when the ANSWER's range (not n) sets the budget → binary search on the answer.
- State a brute force and its cost, then justify moving toward the budget.
- Explain why a correct O(n^2) can score worse than a planned O(n).
Practice queue
Grind these in order. For each, cover the story and predict the target complexity from constraints before reading the ask.
- Two Sum (1) — Easy · your first constraint read. (spaced-repeat anchor: +7d)
- Best Time to Buy and Sell Stock (121) — Easy · n forbids the pair scan.
- Contains Duplicate (217) — Easy · budget invites a set.
- Subsets (78) — Medium · tiny n invites 2^n.
- Search in Rotated Sorted Array (33) — Medium · problem states O(log n).
- Koko Eating Bananas (875) — Medium · answer range sets budget. (spaced-repeat anchor: +21d)
- Capacity To Ship Packages Within D Days (1011) — Medium · same shape as Koko.
- Median of Two Sorted Arrays (4) — Hard · the statement mandates O(log(m+n)).