Algorithm design paradigms are the small set of general strategies from which concrete algorithms are assembled, and four of them account for the overwhelming majority of what practitioners write. Brute force enumerates every candidate solution and is perfectly correct on small inputs, but its combinatorial blowup makes it useless beyond trivial scale, so the first duty of a designer is to ask whether the problem admits a structurally better formulation rather than a faster machine. Divide and conquer splits a problem into independent subproblems of the same type, solves them recursively, and combines the answers, as merge sort does when it halves a list, sorts each half, and merges them in linear time for an overall cost of order n log n; the same shape powers Karatsuba multiplication, the fast Fourier transform used in signal processing, and the closest pair problem in geometry. Greedy algorithms make a locally optimal choice at each step and rely on an exchange argument or a matroid structure to guarantee global optimality; Huffman coding, Dijkstra shortest paths, Kruskal and Prim minimum spanning trees, and the earliest deadline first scheduling heuristic all succeed, while the change-making problem shows how badly a locally attractive option can fail when no such guarantee exists. Recognising which paradigm applies is itself an active search process, and a few habits make it faster. Write the naive solution first and ask whether its work is duplicated, since duplicated work almost always signals an opportunity for divide and conquer or memoization. Ask whether the problem can be sorted and then scanned greedily, since ordering is frequently the hidden source of an optimal strategy. Ask whether a partial answer can be extended without regret, which is the greedy signature, and ask whether the constraints of the problem can be encoded as a graph, which unlocks an entire library of known solutions. Divide and conquer deserves a second observation, because its performance rests entirely on the cost of the combine step: merging two sorted lists is linear, but merging subsets by rescanning all pairs is quadratic, so a divide and conquer algorithm with a careless combine step can end up no better than brute force. Greedy deserves an equally practical warning, since the correctness proof is not a formality but the entire reason the technique may be used, and in an industry setting an unproved greedy heuristic should be recognized as a guess whose failure rate must be measured against the best available alternative. Backtracking adds the dimension of search order, because the order in which choices are explored determines how quickly a satisfying assignment is found, and a good ordering plus a cheap bound often transforms an intractable instance into a solved one. Backtracking and branch and bound explore a search space systematically while pruning on partial evaluation, which is essential for problems such as the traveling salesman, constraint satisfaction, and scheduling with deadlines. Dynamic programming differs from divide and conquer in that the subproblems overlap, so their results are memoized instead of recomputed, which converts exponential work into a polynomial product of smaller state spaces, and the recognition skill that matters most is learning to see which of the four shapes a problem has. Amortized analysis, formalized in the 1980s, completes the picture by bounding the average cost of a sequence of operations rather than the worst cost of any single one, which is precisely why a dynamically resized array, which copies its contents occasionally, still performs amortized constant time insertion and why a disjoint set structure with path compression and union by rank is effectively constant time despite a logarithmic worst case. Randomized algorithms add a further axis, replacing absolute guarantees with high probability ones, and they became the foundation of modern cryptography as well as of the randomized response techniques used in large databases. Parallel and concurrency oriented patterns round out the list, including divide and conquer across machines, work stealing in a task queue, and the producer consumer pipeline that turns a single threaded recursive program into a parallel one. To read an unfamiliar algorithm, it helps to ask which paradigm it embodies and which cost model it assumes, because the paradigm predicts the shape of the recursion, the memory access pattern, and the kinds of inputs that will hurt it, and that prediction is worth more than the pseudocode itself. Complexity theory also calibrates expectations about what is possible in principle. Problems are classified by the resources required to solve them, and the class of problems solvable in polynomial time sits beside the class whose membership can be verified quickly but for which no polynomial algorithm is known, a category that contains thousands of natural scheduling, routing, and configuration problems. Proving that such a problem belongs to that category does not make it unsolvable, but it does explain why engineers must fall back on heuristics, approximations, or restricted input classes, and it explains the persistence of integer programming solvers and constraint programming frameworks in industrial software. Parameterized and approximation algorithms formalize two escape routes, trading an exact answer for a provable bound on error in exchange for tractable running time, and both have moved from textbooks into production systems. Learning complexity therefore does more than prepare for examinations: it teaches the discipline of stating what is known, what is assumed, and where the proof stops, which is exactly the posture required when an analysis is used to justify a design decision to a skeptical colleague.