Competitive Programming Series — Session 2: Recursion and Backtracking
After covering the foundational building blocks in Session 1, the next step is one of the most important problem-solving techniques in all of programming: recursion . And once recursion feels comfortable, it unlocks a powerful search strategy called backtracking . These two concepts appear everywhere in competitive programming — Fibonacci, binary search, tree traversal, merge sort, dynamic programming, N-Queens, and more. They deserve their own spotlight. 🌟 What Is Recursion? A function is recursive if it calls itself. Instead of solving a problem in one go, a recursive function breaks it into a smaller version of the same problem, solves that, and repeats — until the problem becomes simple enough to answer directly. Three things define every recursive solution: The problem is expressed in terms of a smaller instance of itself Each call reduces the problem size There is a point where the problem becomes trivial and no further calls are needed — this is the base case The Nested Box Analogy Think of recursion like opening nested boxes. A big box contains a smaller box, which contains another, and so on. Eventually you find the item you were looking for. That innermost box is the base case. Without it, you would keep opening boxes forever — which is how you get a stack overflow, not a solution. Base Case and Recursive Case Every recursive function has exactly two parts: Recursive case — the problem is reduced in size and the function calls itself again. Base case — the terminating condition. No further recursive call is made. The function returns a direct answer. Both are non-negotiable. A function without a base case will keep calling itself, consuming stack memory until the program crashes. Example: Factorial 5! = 5 × 4! 4! = 4 × 3! 3! = 3 × 2! 2! = 2 × 1! 1! = 1 ← base case Each step reduces the problem by one. When the function hits 1! = 1 , it stops, and the results unwind back up the call stack. In pseudocode: function factorial(n): if n == 1: return 1 # base cas