A Leaner Fibonacci
Building Fibonacci from the bottom up brings fib down to time, but it uses an array of integers. Look at what the loop reads. Each entry f[i] uses only the two entries just before it. Once the loop moves past those entries, they are never read again. So we do not really need the whole array. We only need the last two values. We can keep those two values in a pair of variables and compute the same answer:
public static int fib(int n) {
if (n <= 1) {
return n;
}
int prev = 0;
int curr = 1;
for (int i = 2; i <= n; i++) {
int next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
Instead of a whole array, we keep a two-cell window that slides up the sequence. We start with the two known values:
prev curr
┌───┐ ┌───┐
start │ 0 │ │ 1 │
└───┘ └───┘
Each pass computes next = prev + curr, then shifts the window forward by one. prev takes curr’s value and curr takes next’s. Here is the first pass, i = 2, computing next:
prev curr next
┌───┐ ┌───┐ ┏━━━┓
i = 2 │ 0 │ │ 1 │ ┃ 1 ┃
└───┘ └───┘ ┗━━━┛
And then shifting:
prev curr
┌───┐ ┏━━━┓
i = 2 │ 1 │ ┃ 1 ┃
└───┘ ┗━━━┛
Every later pass does the same thing at the next index. By the final pass, curr holds the answer:
prev curr
┌───┐ ┏━━━┓
i = 5 │ 3 │ ┃ 5 ┃
└───┘ ┗━━━┛
The loop still runs from 2 to n doing constant work each pass, so the time is still . The space changed. We now keep three variables, prev, curr, and next, and that count does not depend on at all. So the auxiliary space is .
Here is the cost of computing the same numbers three different ways:
fib version |
Time | Auxiliary Space |
|---|---|---|
| recursive | ||
| bottom up with an array | ||
| bottom up with three variables |
Going from the first row to the second improved the time, and the space stayed the same. Going from the second row to the third improved the space, and the time stayed the same. A change to an algorithm can improve one cost without changing the other.