class Solution {
public int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int constant = 1000000007;
int minusOne = 1, minusTwo = 0, fib = 0;
for (int i = 2; i <= n; i++) {
fib = (minusOne + minusTwo) % constant; // must
minusTwo = minusOne;
minusOne = fib;
}
return fib;
}
}
Think Fibonacci sequence as following form:
[1 1]^n = [F(n+1) F(n))]
[1 0] [F(n) F(n-1)]
To get F(n), compute the nth matrix.
It’s important to use FME, or the time complexity will be the same as Solution 1.
The Solution 2 contains some redundant computations. We just need F(n+1) and F(n). Follow this idea, we can get two equations for just computing necessaries elements in the matrix. See “Fast Doubling” in DEVONThink.
Another way with same idea is from SICP-Exercise 1.19:
Consider transformation T(p, q), which transforms pair (a, b) according to a <- bq+aq+ap, b <- bp+aq. It can be represented as a matrix:
[q+p, q]
[q, p]
(a, b) start from (1, 0) and (p, q) start from (0, 1)
To apply FME, we need to find p' and q' , so apply we apply T(p',q') to (a, b), we get the same effect of applying T(p, q) twice
Below equations can be easily obintained:
q' = q^2 + 2pq
p' = q^2 + p^2
Code:
(define (fib n)
(fib-iter 1 0 0 1 n))
(define (fib-iter a b p q count)
(cond ((= count 0) b)
((even? count)
(fib-iter a
b
(+ (square p) (square q))
(+ (* 2 p q) (square q))
(/ count 2)))
(else (fib-iter (+ (* b q) (* a q) (* a p))
(+ (* b p) (* a q))
p
q
(- count 1)))))