All of algorithms on a few pages
Five cheat sheets you can keep open while you study, or print for review: asymptotic notation, sums and recurrences, the design strategies with runnable templates, the complexity of every algorithm on this site, and the Forge Pseudocode language reference.
Acronyms used on this page: Traveling Salesman Problem (TSP), Dynamic Programming (DP), Greatest Common Divisor (GCD), Depth-First Search (DFS), Breadth-First Search (BFS), Minimum Spanning Tree (MST), Binary Search Tree (BST), Adelson-Velsky–Landis tree (AVL), Longest Common Subsequence (LCS), Knuth–Morris–Pratt (KMP), Directed Acyclic Graph (DAG), Strongly Connected Components (SCC), Longest Increasing Subsequence (LIS), Least Recently Used (LRU), Least Common Multiple (LCM), Boolean satisfiability (SAT), First-Fit Decreasing (FFD), input/output (I/O), deterministic Polynomial time (P), Nondeterministic Polynomial time (NP).
Asymptotics
Use it when you need to compare two running times, prove a bound, or say which efficiency class an algorithm is in. Everything here follows Levitin Chapter 2 (§2.1–2.2), re-expressed with our own examples.
1. The three notations in one table
Let t(n) be the running time (or basic-operation count) and g(n) a simple comparison function like n2.
| Notation | Read it as | Formal definition (there exist c > 0 and n0 such that for all n ≥ n0) | Think of it as |
|---|---|---|---|
| t(n) ∈ O(g(n)) | "big-oh": grows no faster than g | t(n) ≤ c g(n) | t ⪯ g — an upper bound |
| t(n) ∈ Ω(g(n)) | "big-omega": grows at least as fast as g | t(n) ≥ c g(n) | t ⪰ g — a lower bound |
| t(n) ∈ Θ(g(n)) | "big-theta": grows at the same rate as g | c2 g(n) ≤ t(n) ≤ c1 g(n) | t ≈ g — a tight bound |
- Θ(g) = O(g)∩Ω(g): to prove Θ, prove both directions.
- The constants c, n0 are yours to choose. Any that work are fine; they do not have to be the smallest.
- Only large n matters. Nothing is promised for n < n0 (that is why a Θ(n2) sort can beat a Θ(n log n) sort on small arrays).
Worked proof. Show ½n(n − 1) ∈ Θ(n2). Upper: ½n(n − 1) = ½n2 − ½n ≤ ½n2 for all n ≥ 0, so c1 = ½. Lower: ½n2 − ½n ≥ ½n2 − ½n·½n = ¼n2 once n ≥ 2, so c2 = ¼, n0 = 2. ∎
2. Rules you use every day
| Rule | Statement | Example |
|---|---|---|
| Constant factors vanish | c·t(n) ∈ Θ(t(n)) for any constant c > 0 | 5n2 ∈ Θ(n2) |
| Sum rule (the bigger part wins) | If t1 ∈ O(g1) and t2 ∈ O(g2) then t1 + t2 ∈ O(max {g1, g2}) | sort (n log n) then scan (n) ⇒ O(n log n) |
| Polynomials | aknk + … + a0 ∈ Θ(nk) when ak > 0 | 3n3 − 100n2 + 7 ∈ Θ(n3) |
| Log base doesn't matter | loga n = logb n/logb a, a constant multiple | log2 n ∈ Θ(log10 n) |
| Transitivity | f ∈ O(g) and g ∈ O(h) ⇒ f ∈ O(h) | n ∈ O(n log n) ⊆ O(n2) |
| Exponent bases do matter | an ∈ o(bn) when a < b | 2n is much smaller than 3n |
| Log of a power | log(nk) = k log n ∈ Θ(log n) | log n100 ∈ Θ(log n) |
3. The limit rule — the fastest way to compare two functions
Compute
| Limit | Conclusion |
|---|---|
| 0 | t has a smaller order of growth: t ∈ O(g) but t ∉ Θ(g) |
| a constant c > 0 | same order: t ∈ Θ(g) |
| ∞ | t has a larger order of growth: t ∈ Ω(g) but t ∉ Θ(g) |
(If the limit does not exist, fall back on the definitions. That almost never happens with algorithm running times.)
L'Hôpital's rule
If t(n) → ∞ and g(n) → ∞ and the derivatives exist, then
Example — log2 n vs. √n. Derivatives: (log2 n)′ = 1/(n ln 2) and (√n)′ = 1/(2√n). Ratio: 2√n/(n ln 2) = 2/(ln 2·√n) → 0. So every logarithm grows slower than every square root (in fact slower than nε for any ε > 0).
Stirling's formula
Two consequences you will use:
- log2 n! ∈ Θ(n log n) — this is why no comparison sort can beat n log n (Chapter 11).
- n! grows faster than an for every fixed a: lim n!/2n = ∞.
Example. Compare n! with 2n using Stirling: n!/2n ≈ √(2πn)(n/(2e))n → ∞ because n/(2e) > 1 once n > 5. ∎
4. Handy identities
- alogb n = nlogb a (turns the Master Theorem's alogb n leaves into a power of n)
- logb(xy) = logb x + logb y, logb(x/y) = logb x − logb y, logb xk = k logb x
- 2log2 n = n, and the number of bits of n is ⌊log2 n⌋ + 1
- ⌊x⌋ ≤ x < ⌊x⌋ + 1 and ⌈x⌉ − 1 < x ≤ ⌈x⌉
- Harmonic numbers: 1 + ½ + … + 1/n = Hn ≈ ln n + 0.5772
5. The basic efficiency classes
Values below are rounded; "fits in about 1 second" assumes about 108 simple operations per second.
| Class | Name | n = 10 | n = 103 | n = 106 | Largest n in about 1 s | Typical algorithms |
|---|---|---|---|---|---|---|
| 1 | constant | 1 | 1 | 1 | any | array access, push/pop, hash lookup (expected) |
| log n | logarithmic | 3.3 | 10 | 20 | any | binary search, balanced-tree operations, exponentiation by squaring |
| n | linear | 10 | 103 | 106 | ∼ 108 | sequential search, maximum element, counting sort (small range) |
| n log n | linearithmic | 33 | 104 | 2·107 | ∼ 5·106 | mergesort, heapsort, quicksort (average), closest pair (divide-and-conquer) |
| n2 | quadratic | 102 | 106 | 1012 | ∼ 104 | selection, bubble and insertion sort; all pairs; element uniqueness by brute force |
| n3 | cubic | 103 | 109 | 1018 | ∼ 500 | definition-based matrix multiplication, Floyd, Warshall, Gaussian elimination |
| 2n | exponential | 103 | 10301 | — | ∼ 26 | all subsets: knapsack by exhaustive search, subset-sum, Tower of Hanoi moves |
| n! | factorial | 3.6·106 | — | — | ∼ 11 | all permutations: Traveling Salesman Problem (TSP) by exhaustive search, assignment by exhaustive search |
Order from slowest-growing to fastest: 1 < log n < √n < n < n log n < n2 < n3 < 2n < n! < nn
6. Common traps
- Big-O is not "the worst case." O/Ω/Θ describe functions. You can give a Θ bound for the best case, the worst case or the average case separately.
- "O(n²)" is not a promise of slowness. n ∈ O(n2) is true — just not tight. Use Θ when you mean "exactly this rate".
- Input size is the size, not the value. For a number n, the size is b = ⌊log2 n⌋ + 1 bits, so a loop running n times is exponential in b.
- Drop constants only at the end. When you count operations, keep the exact sum; simplify to Θ last.
- Don't compare exponents of different bases by eye: 4n = (2n)2 is not Θ(2n).
Sums & Recurrences
Use it when you have turned a loop into a sum or a recursive algorithm into a recurrence and now need a closed form. The content matches what Levitin collects in Appendix A (sums) and Appendix B (recurrences), written in our own words with our own worked examples.
1. Sum formulas to know by heart
| # | Sum | Closed form | Order |
|---|---|---|---|
| S1 | ∑i=lu 1 | u − l + 1 | — |
| S2 | ∑i=1n i = 1 + 2 + … + n | n(n + 1)/2 | Θ(n2) |
| S3 | ∑i=1n i2 | n(n + 1)(2n + 1)/6 | Θ(n3) |
| S4 | ∑i=1n ik | ≈ (nk+1)/(k + 1) | Θ(nk+1) |
| S5 | ∑i=0n ai (for a ≠ 1) | (an+1 − 1)/(a − 1) | Θ(an) if a > 1 |
| S6 | ∑i=0n 2i | 2n+1 − 1 | Θ(2n) |
| S7 | ∑i=1n i 2i | (n − 1)2n+1 + 2 | Θ(n2n) |
| S8 | ∑i=1n 1/i (harmonic) | ≈ ln n + 0.5772 | Θ(log n) |
| S9 | ∑i=1n log i = log n! | ≈ n log n | Θ(n log n) |
| S10 | ∑i=0n−1(n − 1 − i) | n(n − 1)/2 | Θ(n2) |
Quick checks with n = 4: S2 gives 10, S3 gives 30, S6 (with n = 3) gives 15, S7 gives 3·32 + 2 = 98 ✔.
2. Manipulation rules
- Constant factor out: ∑ c ai = c ∑ ai
- Split a sum of terms: ∑(ai±bi) = ∑ ai±∑ bi
- Split the range: ∑i=lu ai = ∑i=lm ai + ∑i=m+1u ai for l ≤ m < u
- Telescoping: ∑i=lu(ai − ai−1) = au − al−1
- Shift the index: ∑i=1n ai−1 = ∑j=0n−1 aj (substitute j = i − 1)
- Bounding instead of solving: ∑i=1n f(i) ≤ n·max f; for increasing f, int0nf(x) dx ≤ ∑i=1n f(i) ≤ int1n+1f(x) dx
3. From loops to sums (non-recursive algorithms)
Recipe (Levitin §2.3):
- Pick the input size n.
- Find the basic operation (usually in the innermost loop).
- Ask whether the count depends only on n, or also on the particular input. If it varies, analyze worst, best (and average) cases separately.
- Write the count as a sum, one ∑ per loop, using the loop's exact bounds.
- Simplify with the formulas above; state the closed form, then the order of growth.
Example — "are all elements distinct?" by brute force.
Worst case (all distinct, or the only duplicate pair is the last one checked):
4. From recursion to recurrences
Recipe (Levitin §2.4): size → basic operation → does the count vary by input? → set up a recurrence with an initial condition → solve it (backward substitution, Master Theorem, or characteristic equation) → order of growth.
4.1 Backward substitution, step by step
- Write the recurrence for n, then for n − 1 (or n/2), and substitute it back in.
- Repeat two or three times until you see the pattern after i substitutions.
- Write that general form with i.
- Choose i so the argument hits the initial condition (for example i = n − 1, or i = k when n = 2k).
- Simplify with the sum formulas, then check the result on a small n.
Worked example A — Tower of Hanoi: M(n) = 2M(n − 1) + 1, M(1) = 1
= 2[2M(n − 2) + 1] + 1 = 22M(n − 2) + 2 + 1
= 23M(n − 3) + 22 + 2 + 1
= 2iM(n − i) + 2i−1 + … + 2 + 1 = 2iM(n − i) + 2i − 1
Set i = n − 1: M(n) = 2n−1·1 + 2n−1 − 1 = 2n − 1 ∈ Θ(2n). Check: M(3) = 2·3 + 1 = 7 = 23 − 1 ✔.
Worked example B — counting binary digits: A(n) = A(⌊n/2⌋) + 1, A(1) = 0
Solve for n = 2k (the smoothness rule says the order of growth carries over to all n):
Set i = k: A(2k) = A(1) + k = k, so A(n) = log2 n ∈ Θ(log n). (The exact answer for every n is ⌊log2 n⌋ additions; the bit count is that plus one.)
Worked example C — the exam favorite: T(n) = T(n/2) + log2 n, T(1) = 0
This is not covered by the basic Master Theorem, because f(n) = log n is not of the form nd. Backward substitution handles it. Let n = 2k, so log2 n = k:
= T(2k−2) + (k − 1) + k
= T(2k−i) + (k − i + 1) + … + (k − 1) + k
Set i = k: T(2k) = T(1) + 1 + 2 + … + k = k(k + 1)/2. Back in terms of n: T(n) = log2 n (log2 n + 1)/2 ∈ Θ(log2 n). Check: T(4) = T(2) + 2 = (T(1) + 1) + 2 = 3 and 2·3/2 = 3 ✔.
Worked example D — x(n) = x(n − 1) + n, x(0) = 0
x(n) = x(n − 2) + (n − 1) + n = … = x(0) + 1 + 2 + … + n = n(n + 1)/2 ∈ Θ(n2).
4.2 Three general solutions (Levitin Appendix B, restated)
| Recurrence type | Recurrence | Unrolled solution |
|---|---|---|
| Decrease-by-one | T(n) = T(n − 1) + f(n) | T(n) = T(0) + ∑j=1n f(j) |
| Decrease-by-a-constant-factor | T(n) = T(n/b) + f(n), n = bk | T(bk) = T(1) + ∑j=1k f(bj) |
| Divide-and-conquer | T(n) = aT(n/b) + f(n), n = bk | T(n) = nlogb a[T(1) + ∑j=1k f(bj)/aj] |
Plug f(n) = log2 n with b = 2 into the second row: ∑j=1k j = k(k + 1)/2 — example C again.
5. The Master Theorem
For T(n) = a T(n/b) + f(n) with a ≥ 1, b ≥ 2 and f(n) ∈ Θ(nd), d ≥ 0:
| Case | Condition | Solution | Where the work is |
|---|---|---|---|
| 1 | a < bd | T(n) ∈ Θ(nd) | at the root (the combine step dominates) |
| 2 | a = bd | T(n) ∈ Θ(nd log n) | spread evenly over logb n levels |
| 3 | a > bd | T(n) ∈ Θ(nlogb a) | at the leaves (there are nlogb a of them) |
The same conclusions hold with O and Ω in place of Θ.
Worked examples
| Algorithm | Recurrence | a, b, d | Compare a with bd | Result |
|---|---|---|---|---|
| Binary search | T(n) = T(n/2) + 1 | 1, 2, 0 | 1 = 20 | Θ(log n) |
| Mergesort | T(n) = 2T(n/2) + n | 2, 2, 1 | 2 = 21 | Θ(n log n) |
| Sum of an array by halves | T(n) = 2T(n/2) + 1 | 2, 2, 0 | 2 > 20 | Θ(nlog2 2) = Θ(n) |
| Karatsuba multiplication | T(n) = 3T(n/2) + n | 3, 2, 1 | 3 > 21 | Θ(nlog2 3) ≈ Θ(n1.585) |
| Strassen | T(n) = 7T(n/2) + n2 | 7, 2, 2 | 7 > 22 | Θ(nlog2 7) ≈ Θ(n2.807) |
| Four half-size products | T(n) = 4T(n/2) + n2 | 4, 2, 2 | 4 = 22 | Θ(n2 log n) |
| Unbalanced combine | T(n) = 2T(n/2) + n2 | 2, 2, 2 | 2 < 22 | Θ(n2) |
| Ternary split | T(n) = 3T(n/3) + n | 3, 3, 1 | 3 = 31 | Θ(n log n) |
When it does not apply: f(n) not polynomial (like log n in example C), subproblems of unequal size (like quicksort's worst case T(n) = T(n − 1) + n), or a subtractive recurrence (T(n − 1)). Use substitution instead.
Recursion-tree picture
Draw the calls level by level. Level i has ai nodes, each doing f(n/bi) work, and there are logb n levels. Add the levels. If the level sums shrink geometrically, the root wins (case 1). If they are equal, multiply by the number of levels (case 2). If they grow, the leaves win (case 3).
6. Linear recurrences with constant coefficients — the characteristic equation
For the homogeneous second-order recurrence
write the characteristic equation ar2 + br + c = 0 and find its roots r1, r2:
| Roots | General solution |
|---|---|
| real and distinct | x(n) = αr1n + βr2n |
| real and equal (r1 = r2 = r) | x(n) = αrn + βnrn |
| complex u±iv | x(n) = γn[α cos(nθ) + β sin(nθ)], γ = √(u2 + v2), θ = arctan(v/u) |
Then use the two initial conditions to find α and β.
Worked example E — x(n) = 5x(n − 1) − 6x(n − 2), x(0) = 1, x(1) = 4. Characteristic equation: r2 − 5r + 6 = 0, roots r1 = 2, r2 = 3. So x(n) = α2n + β3n. From x(0): α + β = 1. From x(1): 2α + 3β = 4. Hence β = 2, α = −1 and x(n) = 2·3n − 2n. Check: x(2) = 5·4 − 6·1 = 14 = 18 − 4 ✔.
Worked example F — Fibonacci, F(n) = F(n − 1) + F(n − 2), F(0) = 0, F(1) = 1. r2 − r − 1 = 0 gives φ = (1 + √5)/2 ≈ 1.618 and φ̂ = (1 − √5)/2 ≈ −0.618, so F(n) = 1/√5(φn − φ̂n) and F(n) ∈ Θ(φn). Because |φ̂| < 1, F(n) is φn/√5 rounded to the nearest integer.
Inhomogeneous with a constant: for x(n) = r x(n − 1) + c with r ≠ 1, add the constant particular solution p = c/(1 − r). Tower of Hanoi: M(n) = 2M(n − 1) + 1 gives p = −1, so M(n) = α2n − 1, and M(1) = 1 forces α = 1: M(n) = 2n − 1, as in example A.
Design Strategies
Use it when you face a new problem and don't know where to start. Follow the flowchart, then copy the template for the strategy it points to. Every template below is real Forge Pseudocode: it runs in the Practice Arena and was checked by
tools/check-pseudocode-snippets.mjs.
Acronyms on this page: Dynamic Programming (DP), Traveling Salesman Problem (TSP), Minimum Spanning Tree (MST), Longest Common Subsequence (LCS), Depth-First Search (DFS), Breadth-First Search (BFS), Adelson-Velsky–Landis (AVL) tree, Binary Search Tree (BST), Nondeterministic Polynomial time (NP).
1. The decision flowchart
Three questions that settle most cases
- What is the smallest version of this problem, and how does the answer for a bigger one reuse it? (decrease, divide, DP)
- If I take the obvious best-looking step, can I prove I never regret it? (greedy — prove it with an exchange argument, or find a counterexample on a tiny input)
- Would the problem be trivial if the data were sorted / in a heap / in a hash table? (transform, space-time)
2. The strategies at a glance
| Strategy | Core move | Typical recurrence or count | Signature problems |
|---|---|---|---|
| Brute force | Do what the definition says | a sum over all pairs or positions | selection sort, string matching, closest pair, element uniqueness |
| Exhaustive search | Generate every candidate, keep the best | 2n subsets or n! permutations | TSP, knapsack, assignment, subset-sum |
| Decrease-and-conquer | Solve one smaller instance, extend it | T(n) = T(n − 1) + f(n) or T(n/b) + f(n) | insertion sort, topological sort, binary search, Euclid, quickselect |
| Divide-and-conquer | Solve several independent smaller instances, combine | T(n) = aT(n/b) + f(n) | mergesort, quicksort, Karatsuba, Strassen, closest pair |
| Transform-and-conquer | Change the representation or the problem | cost of the transform + cost of the easy version | presorting, Gaussian elimination, heaps, AVL and 2-3 trees, Horner, reductions |
| Space-time trade-off | Precompute a table or index | extra memory Θ(range) or Θ(n) | counting sort, Horspool, Boyer–Moore, hashing, B-trees |
| Dynamic programming | Solve each overlapping subproblem once, in a table | table size × work per cell | coin-row, change-making, knapsack, LCS, optimal BST, Warshall, Floyd |
| Greedy | Take the locally best piece; never undo | often a sort plus a heap: Θ(n log n) | Prim, Kruskal, Dijkstra, Huffman, activity selection |
| Iterative improvement | Start feasible; improve until no move helps | number of improving steps × cost per step | simplex, maximum flow, bipartite matching, stable marriage |
| Backtracking / branch-and-bound | Build partial solutions; abandon hopeless ones early | exponential worst case, much less in practice | n-queens, subset-sum, Hamiltonian circuit, knapsack, assignment |
| Approximation | Accept a provably near-optimal answer quickly | polynomial | twice-around-the-tree TSP, greedy knapsack, first-fit decreasing bin packing |
3. Templates in Forge Pseudocode
Each template is the smallest real algorithm that shows the strategy's shape. Keep the shape, swap the details.
Brute force — check every pair
Cost: ∑i=0n−2(n − 1 − i) = n(n − 1)/2 comparisons in the worst case.
Exhaustive search — try every subset
Cost: Θ(n2n). Fine for n ≤ 20, hopeless for n = 60.
Decrease-and-conquer — by one (insertion sort)
Decrease-and-conquer — by a constant factor (binary search)
Decrease-and-conquer — variable size (Euclid)
Divide-and-conquer — mergesort
Recurrence: C(n) = 2C(n/2) + (n − 1) comparisons in the worst case, so Θ(n log n) by the Master Theorem.
Transform-and-conquer — presort, then scan
Cost: Θ(n log n) for the sort + Θ(n) for the scan, instead of Θ(n2).
Space-time trade-off — distribution counting
Cost: Θ(n + (u − l)), with no key comparisons at all. Stable, because the last loop runs right to left.
Dynamic programming — coin-row
The recipe: (1) define what a table cell means in words, (2) write the recurrence, (3) find the base cases, (4) fill the table in an order where every cell's inputs are ready, (5) trace back if you need the choices.
Greedy — activity selection
Why it is safe: the activity that ends first leaves the most room for the rest (an exchange argument). With the sort, the cost is Θ(n log n).
Iterative improvement — augmenting paths (bipartite matching)
Each successful augmentation adds one matched pair; when none exists, the matching is maximum (Levitin §10.3).
Backtracking — n-queens
Branch-and-bound — knapsack with an optimistic bound
The bound prunes every branch that cannot beat the best complete solution found so far (Levitin §12.2).
4. Proof tools that go with each strategy
| Strategy | How you argue it is correct | How you get its cost |
|---|---|---|
| Brute force, iterative loops | loop invariant (initialization, maintenance, termination) | sums |
| Decrease / divide-and-conquer | induction on n | recurrences, Master Theorem |
| Dynamic programming | the recurrence is correct (optimal substructure) + fill order | table size × work per cell |
| Greedy | exchange argument, or "greedy stays ahead" | usually sort + heap operations |
| Iterative improvement | a certificate of optimality (min cut, no augmenting path) | number of iterations × cost each |
| Backtracking / branch-and-bound | every pruned branch provably contains no better solution | worst case exponential; measure in practice |
Complexity Table
Use it when you need the running time of an algorithm at a glance, or want to compare two algorithms for the same job. Chapters 1–12 follow Levitin; Chapters 13–17 are the Beyond-the-textbook lessons.
How to read it. Times count the basic operation named in the lesson (key comparisons for sorting and searching, multiplications for arithmetic). "Space" is the extra memory beyond the input. In graph rows, V and E are the numbers of vertices and edges. "Stable" means equal keys keep their input order; "in place" means Θ(1) extra array memory (a recursion stack may still be used). A dash means the idea does not apply.
Acronyms: Greatest Common Divisor (GCD), Depth-First Search (DFS), Breadth-First Search (BFS), Traveling Salesman Problem (TSP), Binary Search Tree (BST), Adelson-Velsky–Landis tree (AVL), Knuth–Morris–Pratt (KMP), Dynamic Programming (DP), Longest Common Subsequence (LCS), Minimum Spanning Tree (MST), Directed Acyclic Graph (DAG), Strongly Connected Components (SCC), Longest Increasing Subsequence (LIS), Least Recently Used (LRU), input/output (I/O), Least Common Multiple (LCM), Boolean satisfiability (SAT), Nondeterministic Polynomial time (NP), First-Fit Decreasing (FFD).
Chapters 1–2 · Introduction and the analysis framework
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Euclid's GCD | 1 | Θ(1) | Θ(log n) | Θ(log n) | Θ(1) | — | gcd(m, n) = gcd(n, m mod n); worst case on consecutive Fibonacci numbers |
| Consecutive-integer GCD check | 1 | Θ(1) | — | Θ(min(m, n)) | Θ(1) | — | try t = min(m, n), min − 1, … until t divides both |
| Sieve of Eratosthenes | 1 | Θ(n log log n) | Θ(n log log n) | Θ(n log log n) | Θ(n) | — | cross out multiples of each prime p, starting at p² |
| Sequential search | 2 | Θ(1) | (n + 1)/2 if found, Θ(n) | n comparisons, Θ(n) | Θ(1) | — | scan until found; a sentinel removes the bounds check |
| Largest element | 2 | n − 1 | n − 1 | n − 1 | Θ(1) | — | keep the best so far; input-insensitive |
| Element uniqueness (brute force) | 2 | Θ(1) | — | n(n − 1)/2, Θ(n²) | Θ(1) | — | compare every pair once |
| Matrix multiplication (definition) | 2 | n³ | n³ | n³ multiplications | Θ(n²) for the result | — | each of n² entries is a length-n dot product |
| Binary digit count | 2 | Θ(log n) | Θ(log n) | ⌊log₂ n⌋ + 1 digits | Θ(1) | — | halve until 1; the recursive version adds Θ(log n) stack |
| Factorial (recursive) | 2 | n multiplications | n | n | Θ(n) stack | — | M(n) = M(n − 1) + 1 |
| Tower of Hanoi | 2 | 2ⁿ − 1 moves | 2ⁿ − 1 | 2ⁿ − 1 | Θ(n) stack | — | move n − 1 aside, move the largest, move n − 1 back |
| Fibonacci, naive recursion | 2 | Θ(φⁿ) | Θ(φⁿ) | Θ(φⁿ) calls | Θ(n) stack | — | the same subproblems recomputed exponentially often |
| Fibonacci, iterative | 2 | Θ(n) | Θ(n) | Θ(n) | Θ(1) | — | keep only the last two values |
| Fibonacci, matrix power | 2 | Θ(log n) | Θ(log n) | Θ(log n) matrix products | Θ(1) | — | power of [[1, 1], [1, 0]] by repeated squaring |
Chapter 3 · Brute force and exhaustive search
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Selection sort | 3 | n(n − 1)/2 | n(n − 1)/2 | n(n − 1)/2 comparisons | Θ(1) | not stable · in place | only n − 1 swaps — good when writes are expensive |
| Bubble sort | 3 | Θ(n²) (Θ(n) with early exit) | Θ(n²) | n(n − 1)/2 comparisons | Θ(1) | stable · in place | adjacent swaps bubble the maximum to the end |
| Brute-force string matching | 3 | Θ(m) | Θ(n) on random text | m(n − m + 1), Θ(nm) | Θ(1) | — | try every alignment of the pattern (length m) in the text (length n) |
| Closest pair (brute force) | 3 | Θ(n²) | Θ(n²) | Θ(n²) | Θ(1) | — | all n(n − 1)/2 pairs; compare squared distances |
| Convex hull (brute force) | 3 | Θ(n³) | Θ(n³) | Θ(n³) | Θ(n) | — | a pair is a hull edge if every other point is on one side |
| TSP (exhaustive search) | 3 | Θ(n!) | Θ(n!) | (n − 1)!/2 tours | Θ(n) | — | fix the start city; every tour and its reverse count once |
| Knapsack (exhaustive search) | 3 | Θ(n·2ⁿ) | Θ(n·2ⁿ) | Θ(n·2ⁿ) | Θ(n) | — | every subset of items |
| Assignment (exhaustive search) | 3 | Θ(n·n!) | Θ(n·n!) | Θ(n·n!) | Θ(n) | — | every permutation of jobs |
| DFS / BFS, adjacency matrix | 3 | Θ(V²) | Θ(V²) | Θ(V²) | Θ(V) | — | scanning a row costs V even for few neighbors |
| DFS / BFS, adjacency lists | 3 | Θ(V + E) | Θ(V + E) | Θ(V + E) | Θ(V) | — | DFS uses a stack (recursion), BFS a queue |
Chapter 4 · Decrease-and-conquer
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Insertion sort | 4 | n − 1 | ≈ n²/4 | n(n − 1)/2 comparisons | Θ(1) | stable · in place | insert A[i] into the sorted A[0..i − 1]; great on almost-sorted data |
| Topological sort (DFS or source removal) | 4 | Θ(V + E) | Θ(V + E) | Θ(V + E) | Θ(V) | — | reverse DFS finishing order, or repeatedly delete a source |
| Permutations (Johnson–Trotter, lexicographic) | 4 | Θ(n!) | Θ(n!) | Θ(n!) | Θ(n) | — | each new permutation is one adjacent swap away (Johnson–Trotter) |
| Subsets (binary counting, Gray code) | 4 | Θ(2ⁿ) | Θ(2ⁿ) | Θ(2ⁿ) | Θ(n) | — | Gray code changes exactly one element per step |
| Binary search | 4 | 1 | ≈ log₂ n | ⌊log₂ n⌋ + 1 comparisons | Θ(1) | — | discard half of the sorted range each step |
| Fake-coin problem | 4 | Θ(log n) | Θ(log n) | ⌈log₃ n⌉ weighings (3 piles) | Θ(1) | — | split into piles and weigh; the light pile holds the fake |
| Russian peasant multiplication | 4 | Θ(log n) | Θ(log n) | Θ(log n) | Θ(1) | — | halve n, double m, add m when n is odd |
| Josephus problem | 4 | Θ(log n) | Θ(log n) | Θ(log n) | Θ(1) | — | J(n) = one-bit cyclic left shift of n in binary |
| Quickselect (Lomuto) | 4 | Θ(n) | Θ(n) | Θ(n²) | Θ(1) | — | partition, then recurse into only the side holding the k-th element |
| Interpolation search | 4 | Θ(1) | Θ(log log n) on uniform keys | Θ(n) | Θ(1) | — | guess the position from the key's value |
| BST search / insert | 4 | Θ(1) | Θ(log n) (random insertions) | Θ(n) | Θ(1) | — | go left or right at each node; degenerates into a list |
Chapter 5 · Divide-and-conquer
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Mergesort | 5 | Θ(n log n) | Θ(n log n) | n log₂ n − n + 1 comparisons | Θ(n) | stable · not in place | sort halves, merge in linear time |
| Quicksort | 5 | Θ(n log n) | ≈ 1.39 n log₂ n | Θ(n²) | Θ(log n) stack (average) | not stable · in place | partition around a pivot; recurse on both sides |
| Binary tree traversals (pre/in/post) | 5 | Θ(n) | Θ(n) | Θ(n) | Θ(height) stack | — | visit root, left subtree, right subtree in some order |
| Tree height, leaf count | 5 | Θ(n) | Θ(n) | Θ(n) | Θ(height) stack | — | answer for the root from the answers for the subtrees |
| Karatsuba multiplication | 5 | Θ(n^1.585) | Θ(n^1.585) | Θ(n^1.585) digit multiplications | Θ(n) | — | three half-size products instead of four |
| Strassen matrix multiplication | 5 | Θ(n^2.807) | Θ(n^2.807) | Θ(n^2.807) | Θ(n²) | — | seven half-size products instead of eight |
| Closest pair (divide-and-conquer) | 5 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | presort by x and y; only a narrow strip needs checking |
| QuickHull | 5 | Θ(n log n) | Θ(n log n) typical | Θ(n²) | Θ(n) | — | the farthest point from a line splits the problem in two |
Chapter 6 · Transform-and-conquer
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Presorting: uniqueness, mode | 6 | Θ(n log n) | Θ(n log n) | Θ(n log n) | depends on the sort | — | after sorting, equal values are neighbors |
| Gaussian elimination | 6 | Θ(n³) | Θ(n³) | ≈ n³/3 multiplications | Θ(1) extra | — | reduce to upper-triangular form, back-substitute |
| AVL tree search / insert / delete | 6 | Θ(log n) | Θ(log n) | Θ(log n) | Θ(n) nodes | — | rotations keep the two subtree heights within 1 |
| 2-3 tree search / insert | 6 | Θ(log n) | Θ(log n) | Θ(log n) | Θ(n) nodes | — | all leaves on one level; full nodes split upward |
| Heap: bottom-up construction | 6 | Θ(n) | Θ(n) | < 2n comparisons | Θ(1) | in place | sift down from the last parent to the root |
| Heap: insert, delete the root | 6 | Θ(1) | Θ(log n) | Θ(log n) | Θ(1) | in place | sift up / sift down along one path |
| Heapsort | 6 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(1) | not stable · in place | build a heap, then delete the maximum n − 1 times |
| Horner's rule | 6 | n | n | n multiplications and n additions | Θ(1) | — | p(x) = (…(aₙx + aₙ₋₁)x + …)x + a₀ |
| Binary exponentiation (left-to-right, right-to-left) | 6 | Θ(log n) | Θ(log n) | ≤ 2⌊log₂ n⌋ multiplications | Θ(1) | — | square for every bit of n, multiply for every 1 bit |
| LCM via GCD | 6 | Θ(1) | Θ(log n) | Θ(log n) | Θ(1) | — | lcm(m, n) = m·n / gcd(m, n) (problem reduction) |
Chapter 7 · Space-time trade-offs
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Comparison counting sort | 7 | n(n − 1)/2 | n(n − 1)/2 | n(n − 1)/2 comparisons | Θ(n) | not in place | an element's position = how many elements are smaller |
| Distribution counting sort | 7 | Θ(n + r) | Θ(n + r) | Θ(n + r) | Θ(n + r) | stable · not in place | count each value in a range of size r, prefix-sum, place |
| Radix sort (least significant digit first) | 7 | Θ(d(n + r)) | Θ(d(n + r)) | Θ(d(n + r)) | Θ(n + r) | stable | d passes of a stable sort, one per digit |
| Bucket sort | 7 | Θ(n) | Θ(n) on uniform keys | Θ(n²) | Θ(n) | stable (with insertion sort) | spread keys into buckets, sort each bucket |
| Horspool string matching | 7 | Θ(n/m) | Θ(n) on random text | Θ(nm) | Θ(alphabet) | — | shift by the table entry for the text character under the pattern's last position |
| Boyer–Moore string matching | 7 | Θ(n/m) | often sublinear | Θ(nm) in simple versions | Θ(m + alphabet) | — | bad-symbol and good-suffix shifts, take the larger |
| KMP string matching | 7 | Θ(n + m) | Θ(n + m) | Θ(n + m) | Θ(m) | — | the prefix function says how far to fall back without rereading the text |
| Hashing, separate chaining | 7 | Θ(1) | ≈ 1 + α/2 probes (successful) | Θ(n) | Θ(n + m) | — | load factor α = n/m keys per cell |
| Hashing, linear probing | 7 | Θ(1) | ≈ ½(1 + 1/(1 − α)) probes (successful) | Θ(n) | Θ(m) | — | clusters form as α approaches 1 |
| B-tree search / insert | 7 | Θ(log n) | Θ(log n) | Θ(log n): about log base m/2 of n disk reads | Θ(n) | — | wide nodes (order m) keep the tree very short |
Chapter 8 · Dynamic programming
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Coin-row problem | 8 | Θ(n) | Θ(n) | Θ(n) | Θ(n), or Θ(1) with two variables | — | F(i) = max(cᵢ + F(i − 2), F(i − 1)) |
| Change-making (DP) | 8 | Θ(nm) | Θ(nm) | Θ(nm) | Θ(n) | — | amount n, m denominations: F(n) = 1 + min over coins of F(n − dⱼ) |
| Robot coin collection | 8 | Θ(nm) | Θ(nm) | Θ(nm) | Θ(nm) | — | F(i, j) = max(F(i − 1, j), F(i, j − 1)) + coin(i, j) |
| 0/1 knapsack (bottom-up) | 8 | Θ(nW) | Θ(nW) | Θ(nW) | Θ(nW) | — | pseudo-polynomial: W is a value, not a size |
| Knapsack memory function | 8 | fewer cells | fewer cells | Θ(nW) | Θ(nW) | — | top-down recursion, computing each needed cell once |
| Binomial coefficient | 8 | Θ(nk) | Θ(nk) | Θ(nk) | Θ(k) possible | — | Pascal's rule C(n, k) = C(n − 1, k − 1) + C(n − 1, k) |
| LCS, edit distance | 8 | Θ(mn) | Θ(mn) | Θ(mn) | Θ(mn), Θ(min) for the value only | — | a 2-D table over prefixes of both strings |
| Optimal BST | 8 | Θ(n³) | Θ(n³) | Θ(n³) | Θ(n²) | — | try every root for every range; Θ(n²) with Knuth's speedup |
| Warshall (transitive closure) | 8 | Θ(n³) | Θ(n³) | Θ(n³) | Θ(n²) | — | allow intermediate vertices 1..k, one k at a time |
| Floyd (all-pairs shortest paths) | 8 | Θ(n³) | Θ(n³) | Θ(n³) | Θ(n²) | — | D[i, j] ← min(D[i, j], D[i, k] + D[k, j]) |
Chapter 9 · Greedy technique
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Prim's MST, unordered array | 9 | Θ(V²) | Θ(V²) | Θ(V²) | Θ(V) | — | grow one tree by its cheapest outgoing edge; good for dense graphs |
| Prim's MST, binary heap | 9 | O(E log V) | O(E log V) | O(E log V) | Θ(V) | — | same idea with a priority queue |
| Kruskal's MST | 9 | O(E log E) | O(E log E) | O(E log E) | Θ(V + E) | — | sort edges; add each one that joins two different trees (union–find) |
| Union–find, union by size + path compression | 9 | Θ(1) | nearly Θ(1) amortized | O(log n) for a single find | Θ(n) | — | shallow trees; flatten them while searching |
| Dijkstra, unordered array | 9 | Θ(V²) | Θ(V²) | Θ(V²) | Θ(V) | — | finalize the closest unfinished vertex; non-negative weights only |
| Dijkstra, binary heap | 9 | O(E log V) | O(E log V) | O(E log V) | Θ(V) | — | same with a priority queue |
| Huffman coding | 9 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | merge the two lightest trees, repeat |
| Greedy change-making | 9 | Θ(m) | Θ(m) | Θ(m) | Θ(1) | — | largest coin first; optimal only for canonical coin systems |
| Activity selection | 9 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | sort by finish time, take the earliest-finishing compatible one |
| Fractional knapsack | 9 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | best value per weight first; split the last item |
Chapter 10 · Iterative improvement
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Simplex method | 10 | — | fast in practice (polynomially many pivots typical) | exponential (Klee–Minty examples) | Θ(mn) tableau | — | walk from vertex to adjacent better vertex |
| Maximum flow, shortest augmenting path | 10 | — | — | O(V E²) | Θ(V + E) | — | augment along the shortest path in the residual network (BFS) |
| Maximum bipartite matching (augmenting paths) | 10 | — | — | O(V E) | Θ(V) | — | flip an alternating path that starts and ends at free vertices |
| Stable marriage (Gale–Shapley) | 10 | Θ(n) proposals | — | Θ(n²) proposals | Θ(n²) preferences | — | free men propose in order; women trade up |
Chapters 11–12 · Limits, and coping with them
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Any comparison sort (lower bound) | 11 | — | ≥ log₂ n! | ≥ ⌈log₂ n!⌉ ≈ n log₂ n comparisons | — | — | a decision tree needs n! leaves |
| Searching a sorted array (lower bound) | 11 | — | — | ≥ ⌈log₂(n + 1)⌉ comparisons | — | — | a ternary decision tree with 2n + 1 leaves |
| SAT: verify a certificate vs. brute force | 11 | — | — | verify Θ(formula size); brute force Θ(2ⁿ · size) | — | — | NP = quick to check, not necessarily quick to find |
| Backtracking (n-queens, subset-sum, Hamiltonian circuit) | 12 | small | usually far less than the full tree | exponential | Θ(n) stack | — | extend a partial solution; back up when it can't be completed |
| Branch-and-bound (assignment, knapsack, TSP) | 12 | small | depends on the bound | exponential | up to exponential (best-first) | — | prune nodes whose bound can't beat the best solution so far |
| Nearest-neighbor TSP | 12 | Θ(n²) | Θ(n²) | Θ(n²) | Θ(n) | — | go to the closest unvisited city; accuracy ratio unbounded |
| Twice-around-the-tree TSP | 12 | Θ(n²) | Θ(n²) | Θ(n²) with Prim | Θ(n) | — | MST walk with shortcuts; ≤ 2 × optimal on Euclidean instances |
| Christofides TSP | 12 | Θ(n³) | Θ(n³) | Θ(n³) | Θ(n²) | — | MST + minimum-weight matching on odd vertices; ≤ 1.5 × optimal (metric) |
| Greedy knapsack approximation (enhanced) | 12 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | best ratio first, compared with the single most valuable item: ≥ ½ optimal |
| First-fit / first-fit decreasing bin packing | 12 | Θ(n²) simple | Θ(n²) | Θ(n²) (Θ(n log n) with a tree) | Θ(n) | — | FFD uses at most about 11/9 × the optimal number of bins (plus a constant) |
| Bisection method | 12 | — | — | ⌈log₂((b − a)/ε)⌉ iterations | Θ(1) | — | halve an interval where the sign changes; always converges |
| Newton's method | 12 | — | quadratic convergence near a simple root | may diverge | Θ(1) | — | xₙ₊₁ = xₙ − f(xₙ)/f′(xₙ) |
Chapters 13–17 · Beyond the textbook
| Algorithm | Ch | Best | Average | Worst | Space | Stable / in place | Key idea |
|---|---|---|---|---|---|---|---|
| Dynamic array append (doubling) | 13 | Θ(1) | Θ(1) amortized | Θ(n) for one resize | Θ(n) | — | double the capacity when full; total copying < 2n |
| Fenwick tree (binary indexed tree) | 13 | Θ(log n) | Θ(log n) | Θ(log n) per update or prefix query | Θ(n) | — | index i covers a range of length lowbit(i) |
| Segment tree | 13 | Θ(log n) | Θ(log n) | Θ(log n) per query/update; Θ(n) build | Θ(n) (about 4n) | — | each node stores the answer for one segment |
| Trie | 13 | Θ(L) | Θ(L) | Θ(L) per word of length L | Θ(total characters) | — | one edge per character; shared prefixes share nodes |
| Skip list | 13 | Θ(1) | Θ(log n) expected | Θ(n) | Θ(n) expected | — | random express lanes over a sorted linked list |
| LRU cache (hash map + linked list) | 13 | Θ(1) | Θ(1) | Θ(1) expected | Θ(capacity) | — | the map finds the node; the list keeps recency order |
| Red-black tree | 13 | Θ(log n) | Θ(log n) | Θ(log n) | Θ(n) | — | colors guarantee height ≤ 2 log₂(n + 1) |
| Bellman–Ford | 14 | Θ(E) (early stop) | Θ(VE) | Θ(VE) | Θ(V) | — | relax every edge V − 1 times; one more round detects a negative cycle |
| A* search | 14 | depends on the heuristic | — | O(E log V) with a consistent heuristic | Θ(V) | — | Dijkstra ordered by g + h, where h never overestimates |
| 0-1 BFS | 14 | Θ(V + E) | Θ(V + E) | Θ(V + E) | Θ(V) | — | a deque: weight-0 edges to the front, weight-1 to the back |
| SCC (Kosaraju, Tarjan) | 14 | Θ(V + E) | Θ(V + E) | Θ(V + E) | Θ(V) | — | two DFS passes (Kosaraju) or one pass with low-links (Tarjan) |
| Bridges and articulation points | 14 | Θ(V + E) | Θ(V + E) | Θ(V + E) | Θ(V) | — | low-link values from one DFS |
| DAG shortest / longest path | 14 | Θ(V + E) | Θ(V + E) | Θ(V + E) | Θ(V) | — | relax edges in topological order |
| Two pointers, sliding window | 15 | Θ(n) | Θ(n) | Θ(n) | Θ(1) or Θ(alphabet) | — | each pointer only moves forward: at most 2n steps |
| Monotonic stack / deque | 15 | Θ(n) | Θ(n) | Θ(n) | Θ(n) | — | every element is pushed and popped at most once |
| Binary search on the answer | 15 | Θ(n log R) | Θ(n log R) | Θ(n log R) | Θ(1) | — | R = range of candidate answers; a feasibility check costs n |
| Kadane's maximum subarray | 15 | Θ(n) | Θ(n) | Θ(n) | Θ(1) | — | best sum ending here = max(x, best ending before + x) |
| LIS, quadratic DP | 15 | Θ(n²) | Θ(n²) | Θ(n²) | Θ(n) | — | L(i) = 1 + max L(j) over earlier smaller elements |
| LIS, patience sorting | 15 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | binary search for the pile each element joins |
| Matrix-chain order | 15 | Θ(n³) | Θ(n³) | Θ(n³) | Θ(n²) | — | interval DP over every split point |
| Held–Karp TSP | 15 | Θ(n²2ⁿ) | Θ(n²2ⁿ) | Θ(n²2ⁿ) | Θ(n2ⁿ) | — | DP over (set of visited cities, last city) |
| Merge intervals | 15 | Θ(n log n) | Θ(n log n) | Θ(n log n) | Θ(n) | — | sort by start, then sweep |
| k-way merge / top-k with a heap | 15 | Θ(N log k) | Θ(N log k) | Θ(N log k) | Θ(k) | — | a heap of size k holds one candidate per list |
| Randomized quicksort | 16 | Θ(n log n) | ≈ 1.39 n log₂ n expected | Θ(n²) (vanishingly unlikely) | Θ(log n) expected | not stable · in place | a random pivot makes every input "average" |
| Karger's min cut (one run) | 16 | Θ(n²) | Θ(n²) | Θ(n²) | Θ(n + E) | — | contract random edges; succeeds with probability ≥ 2/(n(n − 1)) |
| Miller–Rabin primality (k rounds) | 16 | O(k log³ n) | O(k log³ n) | O(k log³ n) | Θ(1) | — | error probability ≤ 4⁻ᵏ |
| Bloom filter (k hash functions) | 16 | Θ(k) | Θ(k) | Θ(k) per insert or query | m bits | — | no false negatives; false-positive rate ≈ (1 − e^(−kn/m))^k |
| Count-Min sketch | 16 | Θ(d) | Θ(d) | Θ(d) per update | Θ(d·w) | — | d rows of w counters; estimates only ever overcount |
| HyperLogLog | 16 | Θ(1) | Θ(1) | Θ(1) per item | m registers | — | standard error ≈ 1.04/√m for distinct counts |
| Reservoir sampling | 16 | Θ(n) | Θ(n) | Θ(n) | Θ(k) | — | keep item i with probability k/i |
| Fisher–Yates shuffle | 16 | Θ(n) | Θ(n) | Θ(n) | Θ(1) | in place | swap A[i] with a random A[j], j ≤ i |
| Rabin–Karp string matching | 15–16 | Θ(n + m) | Θ(n + m) expected | Θ(nm) | Θ(1) | — | rolling hash of each window; verify on a hash match |
| Z-function string matching | 15 | Θ(n + m) | Θ(n + m) | Θ(n + m) | Θ(n + m) | — | reuse the rightmost matched window ([l, r] box) |
| External merge sort | 17 | Θ((N/B) · log base M/B of (N/B)) | same | same I/Os | Θ(M) memory | stable (if runs merge stably) | sort memory-sized runs, then multi-way merge |
Pseudocode
Forge Pseudocode is the Levitin-style pseudocode used in every lesson, simulation and Practice Arena problem. It is not "pretend" code: the Arena runs it, counts its operations and grades it. If you can write it on an exam, you can run it here. Every example on this page was executed by the real interpreter (
docs/engine/forge-pseudo.js) withnode tools/check-pseudocode-snippets.mjs.
1. The shape of an algorithm
- A program is one or more
ALGORITHM Name(parameters)blocks. The first one is the entry point (the Arena calls the name given in the problem). - Indentation defines blocks — 4 spaces per level, exactly like the book.
end,endif,od,{,}lines are tolerated and ignored. //starts a comment. The header comments (purpose, Input, Output) are a habit worth keeping.A[0..n-1]in a header binds n to the array's length.A[l..r]bindslandrto the bounds the caller passed.A[1..n]gives you a 1-based view.
2. Values, assignment and arithmetic
| You write | Meaning | Plain-keyboard alternative |
|---|---|---|
x ← 5 | assignment | x <- 5 or x := 5 |
= ≠ < ≤ > ≥ | comparisons (= is equality, never assignment) | != <= >= |
and or not | logic, short-circuit (and stops at the first false) | && || ! |
+ − × / div mod ^ | arithmetic; / is real division; div rounds down | - * ** % |
⌊x⌋ ⌈x⌉ |x| | floor, ceiling, absolute value | floor(x) ceil(x) abs(x) |
2n n² | implicit multiplication and squares are fine | 2 * n, n^2 |
∞ | infinity (bigger than every number) | infinity |
true false null | booleans and "no value" | NIL also means null |
"text" 'a' | strings and characters (strings can be indexed: s[0]) |
Several statements can share a line when separated by ; — for example i ← 0; j ← n - 1.
3. Decisions
then is optional, and a short body can stay on the same line: if A[i] > m then m ← A[i].
4. Loops
| Form | Example |
|---|---|
| counting up | for i ← 0 to n - 1 do (both ends included) |
| counting down | for i ← n - 1 downto 0 do |
| with a step | for i ← 0 to n - 1 step 2 do |
| over elements | for each x in A do |
| over pairs | for (u, w) in edges do (each element is a list like [u, w]) |
| while / repeat | while cond do · repeat … until cond |
| leave early | break, continue, return |
5. Arrays, views and copies
- Make arrays with
array(n, fill)and 2-D tables withmatrix(rows, cols, fill); read cells asM[i, j]orM[i][j]. - List literals:
[1, 2, 3],[].append(L, x)adds to the end; writing one past the end also extends the array. copy A[0..m-1] to B[0..m-1]copies element by element (Levitin's phrasing).length(A)works on arrays and strings.
6. Recursion and multiple results
7. Records (nodes)
A record is created with new Name; fields appear when you assign them. A field that was never assigned is null.
8. Built-in data structures
| Structure | Create | Operations |
|---|---|---|
| stack | S ← stack() | push(S, x), pop(S), top(S), isEmpty(S) |
| queue | Q ← queue() | enqueue(Q, x), dequeue(Q), front(Q), isEmpty(Q) |
| map (dictionary) | M ← map() | M[k] ← v, M[k], contains(M, k), get(M, k, default), keys(M), values(M), remove(M, k) |
| set | S ← set() | add(S, x), contains(S, x), x in S |
| priority queue | Q ← priorityQueue() (min) or maxPQ() | insert(Q, item, priority), deleteMin(Q) / deleteMax(Q) (return the item), peek(Q), isEmpty(Q) |
9. More built-in functions
| Function | Result |
|---|---|
min(a, b, …), max(…) | smallest / largest argument (or of one list) |
abs, sqrt, floor, ceil, round, pow(a, b) | the usual math |
log2(x) or lg(x), ln(x) | logarithms |
sum(A), sorted(A), reversed(A), reverse(A) | total; sorted copy; reversed copy; reverse in place (returns A) |
range(a, b) | the list [a, a+1, …, b] (both ends included) |
indexOf(A, x) | first index of x, or −1 |
even(n), odd(n) | parity tests |
ord(c), chr(k), int(s), str(x) | character codes and conversions |
random(a, b) | a random integer in a..b (seeded, so runs repeat exactly) |
print x, y | writes a line to the Output panel |
x in L | membership test for lists, sets and map keys |
(Top-level lines outside any ALGORITHM run first — handy for quick experiments.)
10. What the Arena counts
When you run pseudocode, the interpreter counts operations so you can check your analysis against reality:
| Counter | What increments it |
|---|---|
| key comparisons | a relational comparison that involves an array element, like A[j] > v |
| comparisons | every relational comparison |
| array reads / writes | every A[i] read / every A[i] ← … |
| assignments, arithmetic, calls, swaps | what the names say |
| steps | every executed statement (a runaway loop stops at 2,000,000) |
Some problems set a budget (for example "at most n − 1 key comparisons") or a growth check (for example "must be Θ(n log n)"), so the efficiency of your solution is graded, not just its answer.
11. Friendly errors (and what they mean)
| Message starts with | Usual cause |
|---|---|
| "Index … is outside A[0..n−1]" | an off-by-one loop bound (to n instead of to n - 1) |
| "I don't know the variable …" | a typo, or a variable used before its first ← |
| "… has not been given a value yet" | reading an array cell nothing wrote to |
| "Stopped after 2,000,000 steps" | a loop whose condition never changes |
| "The recursion went too deep" | a missing or unreachable base case |