写一个函数,输入 n
,求斐波那契(Fibonacci)数列的第 n
项。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入:n = 2
输出:1
示例 2:
输入:n = 5
输出:5
提示:
- 0 <= n <= 100
答案:
1,递归解决
之前讲356,青蛙跳台阶相关问题的时候提到过斐波那契数列,代码比较简单
public int fib(int n) {
if (n < 2)
return n;
return fib(n - 1) + fib(n - 2);
}
当n很大的时候可能会出现数字溢出,所以我们需要用结果对1000000007求余,但实际上可能还没有执行到最后一步就已经溢出了,所以我们需要对每一步的计算都要对1000000007求余,代码如下
int constant = 1000000007;
public int fib(int n) {
if (n < 2)
return n;
int first = fib(n - 1) % constant;
int second = fib(n - 2) % constant;
return (first + second) % constant;
}
之前讲过斐波那契数列递归的时候会造成大量的重复计算,比如就计算fib(6)为例来看下
我们看到上面相同颜色的都是重复计算,当n越大,重复的越多,所以我们可以使用一个map把计算过的值存起来,每次计算的时候先看map中有没有,如果有就表示计算过,直接从map中取,如果没有就先计算,计算完之后再把结果存到map中。
int constant = 1000000007;
public int fib(int n) {
return fib(n, new HashMap());
}
public int fib(int n, Map<Integer, Integer> map) {
if (n < 2)
return n;
if (map.containsKey(n))
return map.get(n);
int first = fib(n - 1, map) % constant;
map.put(n - 1, first);
int second = fib(n - 2, map) % constant;
map.put(n - 2, second);
int res = (first + second) % constant;
map.put(n, res);
return res;
}
看一下运行结果
2,非递归解法
我们还可以把斐波那契递归改为非递归,代码很简单,可以看下
public int fib(int n) {
int constant = 1000000007;
int first = 0;
int second = 1;
while (n-- > 0) {
int temp = first + second;
first = second % constant;
second = temp % constant;
}
return first;
}
看一下运行结果