Course 3.2Lesson 3 of 5
Many problems fit recursion: the sum of 1 to n, a power, the digits of a number and the Fibonacci numbers. Each has a base case and a smaller problem. The simple Fibonacci function calls itself twice, and the same small values are worked out again and again, so the number of calls grows very fast: 177 calls for n equal to 10, and 21891 for n equal to 20. A loop is often faster and uses less memory, while recursion is often clearer, especially for problems that break into smaller copies of themselves. Anything that can be done with recursion can be done with a loop.
Try the code and the simulations beside the lesson.
After this lesson you can
| Function | Base case | Recursive case |
|---|---|---|
sum_to(n) | n == 0 gives 0 | n + sum_to(n - 1) |
power(b, e) | e == 0 gives 1 | b * power(b, e - 1) |
count_digits(n) | n < 10 gives 1 | 1 + count_digits(n // 10) |
fibonacci(n) | n < 2 gives n | the sum of the two before it |
In each case, the problem gets smaller by one step: one less, one less exponent, one less digit.
Each number is the sum of the two before it. In code, that is exactly the definition: fibonacci(n) is fibonacci(n - 1) + fibonacci(n - 2). The function calls itself twice. This is short and beautiful. But there is a cost.
Predict first. How many calls does fibonacci(20) make? A few dozen? A few thousand? More?
The counts are 15, 177, 1973 and 21 891. For each step of 5 in n, the calls grow about eleven times. Why? Look at fibonacci(5). It needs fibonacci(4) and fibonacci(3). But fibonacci(4) also needs fibonacci(3). So fibonacci(3) is worked out twice, and fibonacci(2) three times, and so on. The same small values are worked out again and again. For fibonacci(50), the simple function would take hours.
The loop version at the end does the same job in n steps. fib_loop(50) is instant. The idea of the loop: keep the last two numbers, and move along.
In the next course, the workshop, you will see a way to keep the beauty of the recursive function and the speed of the loop: a memory in a dictionary.
Each step of n multiplies the calls by about 1.6. At n = 30 the simple version makes more than a million calls.
Anything that can be done with recursion can be done with a loop, and the other way round. So which one?
| Recursion | Loop | |
|---|---|---|
| Speed | slower: every call costs time | usually faster |
| Memory | the call stack grows | a few variables |
| Limit | about 1000 calls deep | none |
| Clearer for | problems that split into smaller copies: folders, trees, towers, subsets | counting, adding, going along a list |
A good rule: if the problem is naturally made of smaller copies of itself, recursion is clear. If you only repeat a step, use a loop. sum_to(n) is better as n * (n + 1) // 2 or a loop. A folder tree is better with recursion.
n. Far too slow.fibonacci needs a base case for both 0 and 1: n < 2.count_digits(n) calling itself with n // 1.Start with two quick questions. Each New numbers gives you a fresh one, so you can practise as long as you like.
Then the labs and the problems:
Try each one on your own first. If you are stuck, open a hint. Then check with Show the answer.
fibonacci(6)? (The values are 0, 1, 1, 2, 3, 5, 8.)Every lesson is open to read. Enrolling also lets you:
Log in to join the discussion.
Loading…
This lesson is free to read. Enroll free to keep your place and take the tests.