题目一:求斐波那契数列的第n项。
写一个函数,输入你,求斐波那契数列的第n项。
最原始的递归方法:
public static int addFibo(int n) {
int[] result = {0,1};
if(n<2)return result[n];
return addFibo(n-1)+addFibo(n-2);
}
优点:递归函数的代码十分的简洁,审阅起来十分具有美感。
缺陷:1)使用递归的效率很低,因为很多数字都被重复计算。例如计算10要计算9和8,计算9要计算8和7,此时8便被计算了两次,随着n的增多,被重复计算的数字将会越来越多。
2)递归函数的实质是函数调用函数本身,而每一次函数的调用都要在内存中分配空间以保存进行参数,返回地址等。而且往栈里弹出数据,插入数据是需要时间的。最重要的是,多层的递归可能造成调用栈溢出。
面试官亲睐的方法:
private static int Fibonacci(int n) {
int[] result = { 0, 1 };
if (n < 2)
return result[n];
int fiboOne = 1;
int fiboTwo = 0;
int fn = 0;
for (int i = 2; i < n; i++) {
fn = fiboOne + fiboTwo;
fiboTwo = fiboOne;
fiboOne = fn;
}
return fn;
}
我们可以使用中间变量将中间值暂且保存起来,实现良好的使用。
题目二:青蛙跳台阶问题。
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级台阶总共需要多少种跳法。
直接先上代码:
private static int Fibonacci(int n) {
if(n<=0)return 0;
if(n==1) {
return 1;
}else if(n==2) {
return 2;
}
int fiboOne = 2;
int fiboTwo = 1;
int fn = 0;
for (int i = 3; i <= n; i++) {
fn = fiboOne + fiboTwo;
fiboTwo = fiboOne;
fiboOne = fn;
}
return fn;
}
分析:我们将跳n阶台阶看成函数f(n),那么f(n)= f(n-1)+f(n-2);因为青蛙只能跳1阶或者2阶;这样我们就能看出这是一个斐波那契数列了,只是初始值1,2可能与前面不同。分析得到,当n=1 时,fn=1;当n=2时,fn=2;
超级青蛙跳台阶:
如果在青蛙跳台阶中,将条件改成:一只青蛙一次可以跳上1个,2个,。。。。n个台阶,此时该青蛙跳上一个n级当台阶总共有多少中跳法?
奉上代码;
private static int superFibonacci(int n) {
if(n==1) return 1;
if(n==2) return 2;
return 2*superFibonacci(n-1);
}
分析:同样的,将青蛙跳台阶看成函数f(n)。第一步有n种跳法;
1)跳1步,还剩下f(n-1)种跳法;
2)跳2步,还剩下f(n-2)种跳法;
3)跳3步,还剩下f(n-3)种跳法;
.......
f(n)= f(n-1)+f(n-2)+f(n-3)+......f(1)+1;1⃣️ 这里的1指的是直接跳n层台阶;
f(n-1)=f(n-2)+(n-3)+f(n-4)+.....f(1)+1;2⃣️
1⃣️减去2⃣️得到:fn = 2f(n-1)
题目一:求斐波那契数列的第n项。