The same problem on the same machine can take a second or a week to solve. What separates the two is rarely the hardware. It's the procedure: the exact sequence of steps the program takes to reach an answer. An algorithm is that procedure, a step-by-step method for solving a problem, written precisely enough for a computer to follow. Choosing a good one is the cheapest performance upgrade in computing, and it's a skill you can learn one pattern at a time.
Work through these in order, since each technique leans on the ones that come before it.
Most of the basics exist to kill a nested loop. Two pointers, fast and slow pointers, and sliding window each collapse a quadratic scan into one pass, while binary search and prefix sums buy their speed from structure the data already has: sorted order in one case, precomputed sums in the other. Recursion is the one idea here bigger than a trick, and tree traversal and sorting are the first places it pays off.
Checks every pair without visiting every pair. Two markers closing in from opposite ends replace an entire nested loop.
Detect an infinite loop without marking a single node. If the fast runner ever laps the slow one, the list has a cycle.
When one element enters and one leaves, the rest of the work is reusable. That single trick turns quadratic scans linear.
Find any entry among a billion sorted items in about 30 looks. Each guess throws away half of what remains.
Pay for one pass up front and the sum of any range becomes a single subtraction, no matter how often you ask.
A function that calls itself sounds like it should run forever. Add a base case and it becomes the cleanest way to shrink a problem down to nothing.
Every node visited exactly once, none missed, none repeated. The order you choose decides what the walk computes.
The setup move for everything else: once data is sorted, searching, merging, and finding duplicates all get cheap.
Single-pass tricks stop working once a problem forces you to make choices. Backtracking explores every choice and unwinds the bad ones, dynamic programming notices it keeps re-solving the same subproblems and stores them, and greedy bets that the locally best choice never needs unwinding at all. Intervals and bit operations are sharper tools for narrower jobs, and depth-first and breadth-first search carry all of this onto graphs.
Try a choice, follow it until it dead-ends, undo it, try the next. Brute force with an undo button, and it solves Sudoku.
When each answer builds on the previous few, store them once and stop recomputing. Exponential problems collapse to a single pass.
Grab the best option available and never reconsider. For the right problems, that shortcut is provably optimal.
Meetings, bookings, IP ranges. Sort by start time and most overlap problems untangle in a single sweep.
Thirty-two yes/no answers packed into one integer, each readable in a single operation. This is the machine's native language.
Commit to one path until it bottoms out, then back up and try the next. The recursion stack remembers the way home.
Explores in expanding rings, so the first time it touches a node is also the shortest way there. No weights needed.
Real maps have weights, and weights break plain breadth-first search. Dijkstra repairs it with a priority queue, A* adds a sense of direction, Bellman-Ford pays extra time to survive negative edges, and Floyd-Warshall answers every pair at once. Prim and Kruskal build the cheapest network rather than the shortest route, while topological sort orders a DAG by its dependencies, the same property that lets DAG shortest paths run in linear time. The remaining two, 2D dynamic programming and the two-heaps pattern, stretch the memo table and the heap to problems with more moving parts.
When a problem has two moving parts, the memo grows into a grid. Edit distance and longest common subsequence live here.
Track the running median of a stream without ever sorting it. Two heaps lean against each other and the answer sits where they meet.
The idea behind your GPS: always extend the cheapest path found so far, and the first arrival is guaranteed optimal.
Dijkstra with a sense of direction. A hint about where the goal lies lets it skip most of the map and still return the best path.
Every shortest path between every pair of nodes, computed by three nested loops you can write from memory.
Shortest paths even when some edges have negative cost, plus a built-in alarm for cycles that make the question unanswerable.
Wires every node together for the least total cost by growing one network outward, always taking the cheapest edge.
Same goal as Prim, opposite move: sort every edge, then keep adding the cheapest one that doesn't close a cycle.
Orders tasks so every prerequisite comes first, or proves that no valid order exists. Build systems run on this.
With no cycles to fear, shortest paths stop needing Dijkstra. One topological pass and every distance falls out in linear time.
Every program is a pile of algorithms, so "algorithms matter" is almost too obvious to say. What's worth spelling out is exactly what a good one buys you:
Algorithms optimize the efficiency of programs, enabling tasks to be completed quickly and using fewer resources. The gap between O(n) and O(n²) is invisible at ten items, but at ten million it's the difference between a fast response and a request that never finishes.
Algorithm complexity measures how much time and space an algorithm needs as its input size n grows. It's usually written in Big-O notation, which describes the upper bound of an algorithm's running time or space requirements in the worst-case scenario.
These two costs usually trade off against each other. Faster algorithms tend to use more memory, and memory-efficient algorithms tend to take more time.
Picking the algorithm is half the problem. The right one makes the solution short and fast, and the wrong one fights you the whole way. Four things to weigh before you commit:
O(V²) to O((V + E) log V) just by swapping an array for a heap, same algorithm, different backing.O(n) search into O(1) by storing an extra copy of everything, and prefix sums and memoization make the same trade. Decide which resource is scarce before you choose.O(n²) approach breezes through a sample input of 50 items and times out the moment n hits 100,000, and the constraints in a problem statement usually tell you which case you're in.