题目描述:
难度简单282
写一个函数,输入
n
,求斐波那契(Fibonacci)数列的第n
项(即F(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
通过次数298,480提交次数826,785
题目链接:力扣
3种解法:
一,动态规划解法:
/**
* 斐波那契数列——动态规划解法:
* 时间复杂度为O(n)
* @param n
* @return
*/
public static int fib(int n) {
//1,特殊情况处理:
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
}
//2,正常情况:
else {
//新建一个数组,用于存放之前的子结果:
int[] array = new int[n + 1];
array[0] = 0;
array[1] = 1;
for (int i = 2; i <= n; i++) {
array[i] = (array[i - 1] + array[i - 2]) % 1000000007;
}
return array[n];
}
}
二,递归解法:
/**
* 斐波那契数列——递归解法:
* @param n
* @return
*/
public static int fib(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
n = (fib(n - 1) + fib(n - 2)) % 1000000007;
return n;
}
}
耗时太长。时间复杂度为O(2^n)。
三,带备忘录的递归:
private List<Integer> list = new ArrayList<>();
/**
* 斐波那契数列——带备忘录的递归解法:
* 单单使用暴力的递归解法太费时费劲了,时间复杂度为O(2^n)
* @param n
* @return
*/
public static int fib3(int n) {
if (!list.contains(0)) {
list.add(0);
}
if (!list.contains(1)) {
list.add(1);
}
if (list.size() > n) {
return list.get(n);
} else {
n = (fib3(n - 1) + fib3(n - 2)) % 1000000007;
list.add(n);
return n;
}
}
直接递归会重复计算,例如fib(4) = fib(3) + fib(2)和fib(3) = fib(2) + fib(1) fib(2)被重复计算。
单单是递归,耗时非常长,时间复杂度为O(2^n),
改造一下,为带备忘录的递归,存储递归过程中的值,去除重复计算,可以大大减少时间复杂度,优化之后,时间复杂度为O(n)。