Visual walkthrough — Lower bound for comparison sorts — Ω(n log n) proof via decision trees
Step 0 — The one thing we assume: comparisons only
WHAT. We consider an algorithm that sorts distinct items but is only allowed one kind of move: pick two items, ask "is this one smaller than that one?", and get back yes or no. Nothing else. No looking at the actual numbers, no arithmetic on them.
WHY. This is the whole game. Everything that follows is squeezing out of this single restriction. If we let the algorithm peek at values (like Counting Sort does), the proof does not apply — and we'll see exactly why at the end.
PICTURE. Two cards face-down. You may only ask "left < right?".

Step 1 — Count the possible answers: there are of them
WHAT. Before any question is asked, the items could be in any order. The number of distinct orderings of different items is Each factor is "how many items are still unplaced when I fill this slot".
WHY. The job of a sort is to name which of these orderings the input actually is (equivalently, which shuffle to undo). So the number of possible correct answers is exactly . That count is the mountain the algorithm must climb.
PICTURE. For there are arrangements — all six shown as little card triples.

Step 2 — Draw the algorithm as a tree of questions
WHAT. Whatever the code does — loops, recursion, swaps — the only thing that steers it differently on different inputs is the answer to a comparison. So the entire behaviour is a binary tree:
- each internal node = one comparison "",
- its two branches = the two answers (left for "yes / <", right for "no / ≥"),
- each leaf = the ordering the algorithm finally announces.
We call this the decision tree.
WHY. This is the key modelling trick: it turns "an algorithm" (hard to reason about) into "a tree" (easy to count). Running the algorithm on one input = walking one root-to-leaf path, taking the branch each answer dictates.
PICTURE. A small decision tree for . Follow a path: two "yes"s send you left-left to a leaf.

Step 3 — Every ordering needs its own leaf
WHAT. Take any two different correct answers, say ordering and ordering . Their leaves must be different leaves.
WHY. A leaf outputs one fixed permutation. If and landed on the same leaf, the algorithm would print the same permutation for both — but they need different answers, so it would be wrong for at least one input. Since all orderings can occur and each needs a distinct reachable leaf: Here just names "how many leaves the tree has".
PICTURE. Two inputs forced to different leaves; the "shared leaf" attempt is crossed out because it must give one input the wrong output.

Step 4 — A binary tree of height has at most leaves
WHAT. Count leaves top-down. At depth 0: 1 node. Each comparison has 2 answers, so each level can at most double the number of nodes. After levels: The exponent is the height; the base is "two answers per question".
WHY. This is the ceiling on how much you can distinguish with yes/no questions. Two answers per node is a hard fact — a comparison cannot return three things. So information capacity is capped at .
PICTURE. Levels of a binary tree, each label showing leaves — the doubling made visible.

Step 5 — Squeeze the two facts together
WHAT. Chain the two inequalities we earned:
- : capacity beats how many leaves you actually have (Step 4).
- : you have at least leaves (Step 3).
- The middle drops out, leaving capacity vs. demand: .
Now take of both sides. is the inverse of "2 to the power" — it asks "2 to what power gives this number?", which is precisely "how many yes/no questions does this many outcomes need?". That is why and not or : our questions are binary.
WHY. turns the towering into the plain we're hunting, and turns into "the number of binary questions its size demands". The inequality survives the log because is increasing (bigger input → bigger output), so it never flips the .
PICTURE. The two curves (capacity) and the flat line (demand): the tree only works once capacity rises above demand, and that crossing point is .

Step 6 — Turn into
WHAT. is exact but ugly. We want a clean, easily-read lower bound. Trick: keep only the top half of the factors of and throw the small ones away. To make "half" precise for every — even or odd — we use the floor (round down): it is the largest whole number , so counts exactly how many factors sit in the top half.
- First ≥: dropping the factors (all ≥ 1) can only shrink the product.
- Second ≥: the kept factors run from up to — at least of them, and every one is .
Take (which turns a product-power into a multiplication):
WHY. We only need a lower bound, so we're allowed to be wasteful and discard the small factors — that keeps the inequality honest while making it dead simple. The floor is not cosmetic: for odd (say ) there is no whole factor equal to , so we anchor on , which really is a factor and really bounds all the kept ones from below. Even just gives exactly — so the same formula covers both parities with no gap. The notation (see Big-O and Asymptotic Notation) means "grows at least this fast, ignoring constants," which is all a lower bound claims.
PICTURE. The factor bars ; the discarded left half greyed out, the kept right half each flattened down to the height — showing the " copies of " bound.

Step 7 — The escape hatch: why Counting Sort isn't bound
WHAT. Counting sort runs in (linear when the key range ) — apparently beating . No contradiction.
WHY. It does count[x]++ — it indexes an array by the value . That's not a comparison; it's peeking at the number itself. Our Step 0 assumption is broken, so the tree model never applied, so the bound never bound it. Same escape for Radix Sort.
PICTURE. Two doors: the "comparisons-only" door leads into the tree (bound applies); the "read the value" door bypasses the tree entirely.

The one-picture summary
Everything on one canvas: orderings feed into a binary tree; each ordering claims a leaf; the tree of height holds at most leaves; so , hence .

Recall Feynman retelling of the whole walkthrough
I hand you cards face-down and blindfold you. Your only move is asking "is this one smaller than that one?" — yes or no. (Step 0) But the cards could be shuffled different ways, and you must name the exact shuffle. (Step 1) Your whole strategy is a tree of yes/no questions; the slowest branch is your worst case. (Steps 2–3) Each shuffle needs its own ending spot, so you need at least endings. But questions create at most endings — each question only doubles your options. (Step 4) So ; taking the "how many binary questions" log gives . (Step 5) Keep just the big half of 's factors and that's already about . (Step 6) So blindfolded sorting must cost — and the only way to go faster is to take the blindfold off and read the numbers, which is exactly the cheat counting/radix sort use. (Step 7)
Active-recall
Why does the decision tree need at least leaves?
Why exactly leaves, not more?
Why take (not ) in Step 5?
What does physically mean?
Why doesn't the bound catch counting sort?
count[x]++), not a comparison, so the comparisons-only premise fails.