Java详解剑指offer面试题10–斐波那契数列
现在要求输入一个整数n,请你输出斐波那契数列的第n项。
我想到的是迭代法,从底向上的方法:先得到f(0)、f(1)的值,然后根据这两个值计算序列后面的值。
package Chap2;
public class Fibonacci {
/**
* 推荐迭代法
*/
public int fib(int n) {
if (n <= 0) {
return 0;
}
int a = 0;
int b = 1;
while (n > 0) {
b = a + b;
a = b - a; // a + b -a -> a = b也就是原来的b赋值给a
n--;
}
return a;
}
}
当然还有递归法,时空开销较大,不推荐。
public int fib2(int n) {
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
return fib2(n-1) +fib(n-2);
}
相关题目–青蛙跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
到达1级台阶只有1种可能,到达2级台阶有2种可能;可记为f(1) = 1,f(2) = 2。要到达3级台阶,可以选择在1级台阶处起跳,也可以选择在2级台阶处起跳,所以只需求到达1级台阶的可能情况 + 到达2级台阶的可能情况,即f(3) = f(2) +f(1)
同理到达n级台阶,可以在n-1级台阶起跳,也可在n-2级台阶起跳,f(n) = f(n-2)+f(n-1)
可以看做是斐波那契数列。
package Chap2;
public class JumpFloor {
/**
* @param target 要到达的第n级台阶
* @return 到达n级台阶总共的跳法可能
*/
public int jumpFloor(int target) {
if (target <= 0) {
return 0;
}
if (target == 1) {
return 1;
}
int a = 1;
int b = 2;
while (target > 1) {
b = a + b;
a = b - a;
target--;
}
return a;
}
}
这道题还有扩展,如下
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
注意和上题的区别。
到达1级台阶只有1种可能,到达2级台阶有2种可能;可记为f(1) = 1,f(2) = 2。要到达3级台阶,可以选择在1级台阶处起跳,也可以选择在2级台阶处起跳,也可直接跳到3级,所以只需求到达1级台阶的可能情况 + 到达2级台阶的可能情况 + 1,即f(3) = f(2) +f(1) + 1同理到达n级台阶,可以在n-1级台阶起跳,可在n-2、n-1、n-3…级台阶起跳,f(n) = f(n-1)+f(n-2)+f(n-3)…+1,如果令f(n-n) = f(0) = 1,上式可表示为f(n) = f(n-1)+f(n-2)+f(n-3)…+f(n-n),有了通项公式找出规律也不是难事了,不过还有种更好理解的思路:前n-1级台阶,每级台阶都有两种选择——跳到此或不跳到此,对于最后一级n级,没得选择,必须跳到这里,所以总共有有2^(n-1)
种跳法。
矩形覆盖问题
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
这个问题本质还是斐波那契数列…
覆盖2*n
的矩形的方法记为f(n)。
- 当最后一步是竖着放时候,说明前一步已经覆盖了
2*(n-1)
,记为f(n - 1) - 当最后一步是横着放的时候,倒数第二次也必然是横着放的。这个状态已经覆盖了
2* (n-2)
,记为f(n - 2)
因为最后一步只有横竖放两种可能,所以将上述两种方法可能性加起来即可。
覆盖2*1
的矩形只有1种方法,覆盖2*2
的矩形有横竖2种方法。于是f(1) = 1, f(2) = 2
这和能跳1级也能跳2级的青蛙是一样的。代码直接copy过来就行!
本文参考文献:
[1]github.com/haiyusun/data-structures