Lesson 33 of 50 intermediate

More Recursion Adventures

Fibonacci, powers, and the famous Tower of Hanoi!

Open interactive version (quiz + challenge)

Real-world analogy

More recursion is like a mirror facing another mirror — you see infinite reflections stretching into the distance. Each reflection is a copy of the original, just a little smaller. But unlike real mirrors, in programming we CHOOSE when to stop looking deeper. That's the beauty of recursion with a base case!

What is it?

This lesson explores more recursion patterns: Fibonacci sequences, power calculations, and the famous Tower of Hanoi puzzle. You'll see when recursion is elegant and clean, when it can be slow, and learn the first hints of how to make it faster. These patterns appear everywhere in competitive programming!

Real-world relevance

Fibonacci numbers appear in nature — the spiral of sunflower seeds, the branching of trees, and the shell of a nautilus all follow Fibonacci patterns. The Tower of Hanoi was invented in 1883 and is used to teach recursion worldwide. Fast power calculation is used in cryptography to keep your online passwords safe!

Key points

Code example

#include <bits/stdc++.h>
using namespace std;

// Fibonacci (simple recursive)
int fib(int n) {
    if (n <= 0) return 0;  // Base case 1
    if (n == 1) return 1;  // Base case 2
    return fib(n - 1) + fib(n - 2);  // Two recursive calls!
}

// Fast power using recursion
long long fastPow(long long base, int exp) {
    if (exp == 0) return 1;  // Base case
    if (exp % 2 == 0) {
        long long half = fastPow(base, exp / 2);
        return half * half;  // Even: square the half
    }
    return base * fastPow(base, exp - 1);  // Odd: reduce by 1
}

// Tower of Hanoi
void hanoi(int n, char from, char to, char helper) {
    if (n == 0) return;  // Base case: no disks to move
    hanoi(n - 1, from, helper, to);  // Move n-1 to helper
    cout << "Move disk " << n << " from " << from << " to " << to << "\n";
    hanoi(n - 1, helper, to, from);  // Move n-1 from helper to target
}

int main() {
    // Fibonacci
    cout << "Fibonacci sequence: ";
    for (int i = 0; i < 10; i++) cout << fib(i) << " ";
    cout << "\n";  // 0 1 1 2 3 5 8 13 21 34
    
    // Fast power
    cout << "2^10 = " << fastPow(2, 10) << "\n";  // 1024
    
    // Tower of Hanoi with 3 disks
    cout << "Tower of Hanoi (3 disks):\n";
    hanoi(3, 'A', 'C', 'B');
    return 0;
}

Line-by-line walkthrough

  1. 1. #include and using namespace std; — our standard setup for competitive programming.
  2. 2. int fib(int n) — the Fibonacci function takes a number n and returns the nth Fibonacci number.
  3. 3. if (n <= 0) return 0; if (n == 1) return 1; — TWO base cases! Fibonacci needs two because each call depends on TWO previous values. fib(0)=0 and fib(1)=1 are the starting points.
  4. 4. return fib(n-1) + fib(n-2); — the recursive case calls fib TWICE: once for n-1 and once for n-2. This is what makes it slow for large n — it branches into two calls each time!
  5. 5. long long fastPow(long long base, int exp) — fast power uses long long because powers can get very large very quickly.
  6. 6. if (exp == 0) return 1; — base case: anything to the power 0 is 1.
  7. 7. if (exp % 2 == 0) — if the exponent is even, we can be clever: calculate the half-power once and square it. This is much faster than multiplying one at a time!
  8. 8. long long half = fastPow(base, exp/2); return half * half; — we only make ONE recursive call and then square the result. This halves the work each time!
  9. 9. void hanoi(int n, char from, char to, char helper) — the Tower of Hanoi function takes: how many disks, which peg they're on, which peg to move to, and which peg to use as a helper.
  10. 10. The hanoi function: move n-1 disks to helper, move the biggest disk to target, then move n-1 disks from helper to target. It's beautifully simple once you trust the recursion!

Spot the bug

#include <bits/stdc++.h>
using namespace std;

int fib(int n) {
    if (n == 1) return 1;
    return fib(n - 1) + fib(n - 2);
}

int main() {
    cout << fib(6) << "\n";
    return 0;
}
Need a hint?
Fibonacci needs TWO base cases. What happens when the recursion reaches fib(0)?
Show answer
The bug is a missing base case! The function only has a base case for n==1, but Fibonacci calls fib(n-2), which eventually reaches fib(0). With no base case for 0, fib(0) calls fib(-1) and fib(-2), leading to infinite recursion and a crash. The fix is to add 'if (n <= 0) return 0;' before the n==1 check. Fibonacci needs TWO base cases: fib(0)=0 and fib(1)=1.

Explain like I'm 5

Imagine you have a pile of different-sized plates and three tables. You need to move all plates from Table A to Table C, but you can only move one plate at a time, and you can NEVER put a bigger plate on top of a smaller plate. The trick is: first move all the small plates out of the way to Table B, then move the biggest plate to Table C, then move the small plates from Table B to Table C. And to move the small plates? You do the same trick again! That's recursion — the same trick, over and over, with smaller groups.

Fun fact

The Tower of Hanoi legend says monks in a temple are moving 64 golden disks between 3 diamond pegs. When they finish, the world will end! At 1 move per second, it would take about 585 BILLION years — roughly 42 times the age of the universe. So we're safe! The minimum moves needed for n disks is 2^n - 1.

Hands-on challenge

Write a recursive function countDigits(n) that returns how many digits a positive number has. For example, countDigits(1234) should return 4, and countDigits(7) should return 1. Hint: the base case is when n < 10 (single digit), and the recursive case divides n by 10. Then use it to find how many digits are in 1000000 (one million)!

More resources

Open interactive version (quiz + challenge) ← Back to course: CP Zero to Hero