斐波那契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
0 <= n <= 100
当数值较大时候会大数溢出,所以要对答案进行取模,而且使用递归的方法内存占用大,运行时间长,容易造成时间超时,所以采用动态规划的方法
- 递归法:
原理: 把 f(n)f(n) 问题的计算拆分成 f(n-1)f(n−1) 和 f(n-2)f(n−2) 两个子问题的计算,并递归,以 f(0)f(0) 和 f(1)f(1) 为终止条件。
缺点: 大量重复的递归计算,例如 f(n)f(n) 和 f(n - 1)f(n−1) 两者向下递归都需要计算 f(n - 2)f(n−2) 的值。
- 记忆化递归法:
原理: 在递归法的基础上,新建一个长度为 nn 的数组,用于在递归时存储 f(0)f(0) 至 f(n)f(n) 的数字值,重复遇到某数字时则直接从数组取用,避免了重复的递归计算。
缺点: 记忆化存储的数组需要使用 O(N)O(N) 的额外空间。
- 动态规划:
原理: 以斐波那契数列性质 f(n + 1) = f(n) + f(n - 1)f(n+1)=f(n)+f(n−1) 为转移方程。
从计算效率、空间复杂度上看,动态规划是本题的最佳解法。
大数越界: 随着 nn 增大, f(n)f(n) 会超过 Int32 甚至 Int64 的取值范围,导致最终的返回值错误。
- 求余运算规则
求余运算规则: 设正整数 x, y, px,y,p ,求余符号为⊙ ,则有 (x + y) ⊙p = (x⊙p + y⊙ p) ⊙p(x+y)⊙p=(x⊙p+y⊙p)⊙p 。
解析: 根据以上规则,可推出 f(n)⊙ p = [f(n-1)⊙ p + f(n-2) ⊙ p] ⊙ pf(n)⊙p=[f(n−1)⊙p+f(n−2)⊙p]⊙p ,从而可以在循环过程中每次计算 sum = a + b⊙ 1000000007 sum=a+b⊙1000000007 ,此操作与最终返回前取余等价。
题解:
Java:
class Solution {
public int fib(int n) {
if(n<=1){
return n;
}
int[] arr = new int[n+1];
arr[0] = 0;
arr[1] = 1;
for (int i = 2; i<=n;i++){
arr[i] = arr[i-1] + arr[i-2];
arr[i] = arr[i]%1000000007;
}
return arr[n];
}
}
public class Solution {
public int Fibonacci(int n) {
if(n<=1){
return n;
}
// int[] arr = new int[n+1];
// arr[0] = 0;
// arr[1] = 1;
int first = 0;
int second = 1;
int res =0;
for (int i = 2; i<=n;i++){
res = (first +second)%1000000007;
first =second;
second = res;
}
// return arr[n];
return res;
}
}
javascrip
/**
* @param {number} n
* @return {number}
*/
var fib = function(n) {
if(n<=1){
return n;
}
// return Fibonacci(n-1)+Fibonacci(n-2);
let array = [0,1];
for(let i = 2;i<=n;i++){
array[i] = array[i-1]+array[i-2];
array[i] = array[i]%1000000007;
}
return array[n];
};