The Runtime Theory
Programming & Algorithms

Algorithms Are Procedures With Costs

Learn to connect an algorithm's correctness argument to the comparisons, branches, and memory accesses it performs.

The Runtime Theory Team7 min read#complexity#searching#graphs#correctness
▸ On this page

An algorithm is a finite procedure for solving a class of problems. A useful explanation answers two questions: why does the procedure produce the right result, and what resources does it consume as the input grows?

Start with the invariant

Consider binary search over a sorted array. The algorithm keeps a range that is known to contain the target if the target exists. At each iteration it examines the middle element and discards the half that cannot contain the target. The invariant is what makes the answer correct; the halving is what makes the search logarithmic.

If there are n items, each comparison reduces the remaining range by roughly half, so the number of iterations grows like log₂(n). That statement describes asymptotic growth, not elapsed time. A binary search may perform fewer comparisons than a linear scan while making less predictable memory accesses. For a tiny array, the simpler scan can still be faster because contiguous data is easy for the processor to fetch and loop over.

Complexity describes a family of inputs

Big-O gives an upper growth bound up to constant factors. It helps compare how work scales, but it hides constants, data distribution, cache behavior, allocation, and the cost of an individual operation. Average-case claims need an explicit model of which inputs are likely. Amortized analysis answers a different question: across a sequence of operations, an occasional expensive operation may be spread over many cheap ones.

Choose a technique from the problem structure

Two pointers exploit order or a moving boundary. Sliding windows maintain a summary for a contiguous range. Divide and conquer splits a problem into smaller pieces and combines their results. Dynamic programming stores answers to overlapping subproblems. Graph algorithms make relationships explicit and then traverse or optimize paths through those edges.

For each technique, write down the state it maintains, the condition that changes it, and the work done per update. Then test edge cases such as empty input, duplicates, overflow boundaries, disconnected graphs, or adversarial ordering. These checks often reveal a missing invariant before a benchmark does.

From paper to machine

An algorithm's data structure controls its access pattern. A binary search jumps across an array; a linked traversal follows pointers; a breadth-first search uses a queue and touches neighbors by layer. Those patterns influence cache locality and branch prediction. Complexity gives a first map; a trace or profile explains a particular implementation's actual cost.

MIT's Introduction to Algorithms course is a useful companion for correctness and analysis.

Not started

Sign in to save your learning progress.

Sign in to save