指这样一个数列:1、1、2、3、5、8、13、21、34、……
F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
是一个线性递推数列。通向公式如下(又称为“比内公式”,是用无理数表示有理数的一个范例):
现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39。
思路:递归的效率低,使用循环方式(复杂度O(n))。
public long fibonacci(int n) {
long result=0;
long preOne=1;
long preTwo=0;
if(n==0) {
return preTwo;
}
if(n==1) {
return preOne;
}
for (int i = 2; i <= n; i++) {
result = preOne+preTwo;
preTwo = preOne;
preOne = result;
}
return result;
}
笔者自己的代码:
public int Fibonacci(int n) {
int fun1 = 0, fun2 = 1;
if (n == 0) return fun1;
if (n == 1) return fun2;
int i;
for (i = 1; i + 2 < n; i += 2) {
fun1 = fun1 + fun2;
fun2 = fun1 + fun2;
}
if (i + 2 == n) fun1 = fun2 + fun1;
return fun1 + fun2;
}
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:对于本题,前提只有 一次 1阶或者2阶的跳法。
a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
e.可以发现最终得出的是一个斐波那契数列:
| 1, (n=1)
f(n) = | 2, (n=2)
| f(n-1)+f(n-2) ,(n>2,n为整数)
我们可以用2*1
的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1
的小矩形无重叠地覆盖一个2*n
的大矩形,总共有多少种方法?
思路:
斐波那契数列:
设2*8
的覆盖方法为 f(8)
,用一个1*2
小矩形覆盖最左边时有两个选择:竖着放一块,或者横着放两块(即f(1)=1;f(2)=2)。
竖着放一块时,记剩下区域覆盖有f(7)
种;
横着放两块时,记剩下区域覆盖有f(6)
种。
则f(8)=f(7)+f(6)
中覆盖方式。
public int Fibonaccik(int n) {
int number = 1;
int sum = 1;
if (n <= 0)
return 0;
if (n == 1) {
return 1;
}
while (n-- >= 2) {//巧妙的存储了斐波那契数列
//2,1 3,2 5,3……
sum += number;
number = sum - number;
}
return sum;
}
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:其实是隔板问题,假设n个台阶,有n-1个空隙,可以用0~n-1个隔板分割,C(n-1,0)+C(n-1,1)+...+C(n-1,n-1)=2^(n-1)
,其中C表示组合。 有人用移位1<<--number
,这是最快的。
组合运算:若表示在 n 个物品中选取 m 个物品,则如存在下述公式:C(n,m)=C(n,n-m)=C(n-1,m-1)+C(n-1,m)。
public int jumpFloor1(int target) {
return (int) Math.pow(2,target-1);
}
int jumpFloor2(int number) {//最快
return 1<<(--number);
}