Fibonacci数列
Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, …,在Fibonacci数列中的数我们称为Fibonacci数。给你一 个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数。
常规方法
首先看到题目,第一想法就是递归实现,简单方便,易于理解。
public int fn(int n) {
return n<=0?0:(n==1?1:fn(n-1)+fn(n-2));
}
虽然写法简单,但是明显能感觉到效率比较低。因为在递归的过程中,会出现大量的重复计算,显然这种方式是不可取的,当n值超出一定范围,程序会非常缓慢,甚至超时宕机。
高效方法
暂存递归
普通方法之所以效率低、计算慢,其原因就是出现大量的重复计算。如果我们将计算过的值暂存起来,实现重复利用。这样就可以避免递归次数,提高性能效率。
int arr[] = new int[n+1];
arr[1] = 1;
public int fn(int n) {
return n<=0?0:(n==1?1:(arr[n]!=0?arr[n]:(arr[n] = fn(n-1)+fn(n-2))));
}
- 定义数组存储第一次计算的结果
- 在递归体中若发现计算过,直接取值避免重复递归
- 数组一定要在递归体外定义
暂存迭代
和上面的思路一样,也是定义一个暂时结构存放已计算过的结果。
public int fn(int n) {
if (n<=0) return 0;
int result[] = new int[n+1];
result[0] = 0;
result[1] = 1;
for (int i=2;i<=n;i++){
result[i] = result[i-1]+result[i-2];
}
return result[n];
}
累加迭代
用上一次计算的结果再计算。
public int fn(int n) {
if (n<=0) return 0;
int pre = 0;
int next = 1;
for (int i=0;i<n-1;i++){
int temp = pre+next;
pre = next;
next = temp;
}
return next;
}