Skip to content
{}

Lesson 06new · v2 format

How to Read a Problem: Constraints, Clues & Complexity Budgets

Before you write a line of code, the problem statement has already told you which algorithm to use.

25 min

01Why it matters & the intuition

Most people who 'can't do LeetCode' can follow any solution once they see it. What they are missing is the step before the solution: reading the problem and narrowing thousands of possible approaches down to one or two. That step is a skill with rules, and this lesson teaches the rules.

You don't need to know the algorithms yet. By the end of this page you will be able to look at a problem and say how fast the solution must be and which family of techniques to try — the rest of the course fills in each family.

Think of it like…

A doctor doesn't try every medicine. They read the symptoms — fever, rash, where it hurts — and each symptom rules whole diseases in or out. The constraints are the patient's vital signs: they tell you how much time you're allowed. The clue words ("sorted", "contiguous", "all combinations", "shortest") are the symptoms: each one points at a family of treatments.

02See it move

Pick a constraint the way it appears in a problem, or drag the slider. Watch which complexity classes survive — the teal row is the slowest solution you're allowed to write.

Complexity budget · ~10⁸ operations per second
interactive
ClassOperationsTime at 10⁸/sVerdict
O(n!)try every ordering∞heat death of the universetoo slow
O(2ⁿ)try every subset∞heat death of the universetoo slow
O(n³)triple loop, interval DP1.0×10^15116 daystoo slow
O(n²)every pair, 2-D DP1.0×10^10100.0 stoo slow
O(n log n)sort, heap, divide & conquer1.7×10^617 msyour budget
O(n)one pass, hash map, window1.0×10^51 msfits
O(log n)binary search17< 1 msfits
›With n = 1.0×10^5, your budget is O(n log n) (sort, heap, divide & conquer). Anything above the teal row would time out.

03Key ideas

Step 1 — Restate it in one line

Write input → output in your own words: "array of prices → max profit from one buy and one later sell". If you can't restate it, you'll solve the wrong problem. Note the output type: a number, a boolean, one item, or all items (a strong hint on its own).

Step 2 — Read the constraints first

Judges allow roughly 10⁸ simple operations per second. So n ≤ 10⁵ means O(n²) = 10¹⁰ is too slow, but O(n log n) ≈ 1.7 × 10⁶ is easy. The constraint is the problem setter telling you the target complexity.

Step 3 — Circle the clue words

"sorted" → binary search or two pointers. "contiguous subarray / substring" → sliding window or prefix sums. "all combinations / every arrangement" → backtracking. "shortest number of steps" → BFS. "number of ways / minimum cost" → dynamic programming. "k-th / top k" → heap or quickselect.

Step 4 — Say the brute force out loud

Always name the simplest correct approach and its cost first. It gives you a fallback, and comparing its cost to the budget tells you exactly how much faster you need to be.

Step 5 — Find the bottleneck

Ask: what does the brute force repeat? Rescanning for a partner → remember what you've seen (hash map). Re-summing overlapping ranges → reuse the previous window. Re-solving the same sub-question → cache it (DP). The structure you pick is whatever removes the repetition.

Edge cases come from constraints too

0 ≤ n means empty input is legal. Negative values break "sliding window on sums". Values up to 10⁹ mean sums can exceed 32-bit ints in other languages. Duplicates allowed? Read it twice.

04Build it from scratch

A clean reference implementation. Read it line by line — then close it and write your own in the lab below.

typescript
// The 5-step read, written as a checklist you can keep next to your editor.
interface ProblemRead {
  restated: string;       // "array of prices -> max profit from one buy then one later sell"
  n: number;              // largest input size from the constraints
  budget: string;         // fastest-growing complexity that still fits ~1e8 operations
  clues: string[];        // words that point at a technique family
  bruteForce: string;     // simplest correct idea + its cost
  bottleneck: string;     // what the brute force repeats
}

// Step 2 made mechanical: the biggest complexity class that fits the budget.
const OPS_PER_SECOND = 1e8;

const CLASSES: [label: string, cost: (n: number) => number][] = [
  ["O(n!)", (n) => { let f = 1; for (let i = 2; i <= n; i++) f *= i; return f; }],
  ["O(2^n)", (n) => 2 ** n],
  ["O(n^3)", (n) => n ** 3],
  ["O(n^2)", (n) => n ** 2],
  ["O(n log n)", (n) => n * Math.log2(Math.max(n, 2))],
  ["O(n)", (n) => n],
];

function complexityBudget(n: number): string {
  for (const [label, cost] of CLASSES) {
    if (cost(n) <= OPS_PER_SECOND) return label; // slowest class that still fits
  }
  return "O(log n)";
}

complexityBudget(12);      // "O(2^n)"   — 12! = 479M is too slow, 2^12 = 4096 is fine
complexityBudget(1e5);     // "O(n log n)"
complexityBudget(1e12);    // "O(log n)" — only binary search / math survives

05Complexity

Constraint saysBudget — aim for
n ≤ 10–11O(n!) — try every ordering—
n ≤ 20–25O(2ⁿ) — try every subset—
n ≤ 300–500O(n³) — triple loop / interval DP—
n ≤ 5,000–10⁴O(n²) — every pair / 2-D DP—
n ≤ 10⁵–10⁶O(n log n) or O(n) — sort, heap, hash, window—
n ≤ 10⁸O(n) with a tiny constant—
n up to 10⁹ – 10¹⁸O(log n) or O(1) — binary search on the answer, math—

06Recognise it in a problem

These phrases in a problem statement should make you reach for a specific tool before you write any code.

If the problem says……reach for
"sorted" array or "find position"Binary search, or two pointers from both ends
"contiguous", "subarray", "substring", "window"Sliding window or prefix sums
"pair / two numbers that add to", "seen before", "duplicate"Hash map or set
"all", "every combination / permutation / subset", n ≤ 20Backtracking — exponential is expected
"shortest path / fewest steps", grid or network, no weightsBFS
"prerequisites", "order tasks", "depends on"Topological sort on a directed graph
"number of ways", "minimum / maximum cost", choices at each stepDynamic programming
"k-th largest", "top k", "closest k"Heap (priority queue) or quickselect
"next greater / smaller element", "days until warmer"Monotonic stack
"merge intervals", "meeting rooms", overlapping rangesSort by start or end, then one scan

07Decode drills

You won’t solve these here. Read each problem the way an experienced engineer would: circle the clues in your head, pick the technique family and the complexity you must hit. Then check the clues you missed.

drill 1/8 · 0 fully decoded

Matching transactions

You are given a list of transaction amounts and a target value. Return true if any two different transactions add up exactly to the target.

Constraints: 2 ≤ n ≤ 10⁵ · −10⁹ ≤ amount ≤ 10⁹

1 · Which technique family fits?
2 · What complexity must the solution hit?

08Check your understanding

Question 1

Q1.Constraints say 1 ≤ n ≤ 2 × 10⁵. Which is the slowest complexity you should aim for?

Question 2

Q2.A problem says n ≤ 18 and asks for the best way to split items into two groups. What does n ≤ 18 suggest?

Question 3

Q3.Why say the brute force out loud before optimising?

Question 4

Q4."Find the length of the longest subarray whose sum is at most K" (all values positive). The strongest clue is…

09Code lab

Write Python(or switch to JavaScript) and run it against real test cases. Python runs inside your browser — nothing is uploaded — and a C++ reference solution is under “Solution”.

Compute the complexity budget

Write budget(n) that returns the most expensive complexity class that still fits — i.e. the first of "O(n!)", "O(2^n)", "O(n^3)", "O(n^2)", "O(n log n)", "O(n)" whose cost for this n is at most 10⁸ operations — or "O(log n)" if none fit. Use n * Math.log2(n) for n log n.

function: budgetPython starts when you get here