斐波那契数列是这样一个数列0,1,1,2,3,5,8,13,21......可以很容易的看出斐波那契数列的规律,斐波那契数列的定义如下:
0 n=0
f(n)= 1 n=1
f(n-1)+f(n-2) n>1
问题:实现一个函数,输入n,求斐波那契数列的第n项
解法一:递归
<span style="font-family:SimSun;font-size:14px;">long long Fibonacci(unsigned int n)
{
if(n <= 0)
return 0;
if(n == 1)
return 1;
return Fibonacci(n-1) + Fibonacci(n - 2);
}</span>
此算法的效率是很低的,会有大量的重复操作,时间复杂度以n的指数方式增加。
调用次数:c(n)是求第n项调用的次数 c(0)=1;c(1)=1;c(n)=c(n-1)+c(n-2)+1;
解法二:循环
为了避免重复计算,可以把已经得到的数列中间项保存起来,直接使用,从上往下算,首先根据f(0),f(1)计算出f(2),再根据f(1),f(2)计算出f(3)...一次类推就可以计算出第n项了。
<span style="font-family:SimSun;font-size:14px;">long long Fibonacci(unsigned n)
{
int result[2] = {0 , 1};
if(n < 2)
return result[n];
long long fibMinusOne = 1;
long long fibMinusTwo = 0;
for(unsigned int i = 2 ; i <= n ; ++i)
{
fibN = fibMinusOne + fibMinusTwo;
fibMinusTwo = fibMinusOne;
fibMinusOne = fibN;
}
return fibN;
}</span>
相关问题1:一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法。
思路:首先考虑简单情况,如果只有1级,那么有1种跳法,如果有2级,有两种跳法,一次跳两级,另一种是分两次跳,每次跳一级。
把n级台阶时的跳法看成是n的函数,记为f(n)。当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数
目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另一种选择是第一次跳2级,此时跳法数目等于后面剩下n-2级台阶的跳法数
目,即为f(n-2)。因此,n级台阶的不同跳法的总数f(n)=f(n-1)+f(n-2)。可以看出这实际上就是斐波那契数列。解法有以上两种。
相关问题2:一只青蛙一次可以跳上1级台阶,也可以跳上2 级……它也可以跳上n 级,此时该青蛙跳上一个n级的台阶总共有多少种跳法?
用f(n)表示青蛙跳上n级台阶的跳法数,青蛙一次性跳上n级台阶的跳法数1(n级跳),设定f(0) = 1;
当n = 1 时, 只有一种跳法,即1级跳:f(1) = 1;
当n = 2 时, 有两种跳的方式,一次跳2级和两次跳每次跳一级:f(2) = f(1) + f(0) = 2;
当n = 3 时,有三种跳的方式,第一次跳出一级后,后面还有f(3-1)中跳法; 第一次跳出二级后,后面还有f(3-2)中跳法;第一次跳出三级后,后面还有f(3-3)中跳法
f(3) = f(2) + f(1)+f(0)=4;
当n = n 时,共有n种跳的方式,第一次跳出一级后,后面还有f(n-1)中跳法; 第一次跳出二级后,后面还有f(n-2)中跳法..........................第一次跳出n级后, 后面有f(n-n)中跳法.
f(n) = f(n-1)+f(n-2)+f(n-3)+..........+f(n-n)=f(0)+f(1)+f(2)+.......+f(n-1)
又因为f(n-1)=f(0)+f(1)+f(2)+.......+f(n-2)
两式相减得:f(n)-f(n-1)=f(n-1)
可以得到递归等式: f(n) = 2*f(n-1) n >= 2
f(n)=2*2*2....*f(0)=2^n-1
相关问题3:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思想:把长条n*2的覆盖问题分解,第一步,若竖着覆盖一个2*1的方块,那么剩下的为2*(n-1)块,否则,若横着覆盖,应用两块,覆盖一个2*2的块,剩下2*(n-2),这两种覆盖的方式都各有一种,这个问题等同于递归f(n)=f(n-1)+f(n-2)
<span style="font-family:SimSun;font-size:14px;">int main()
{
long long n,k,i,j,t;
while(scanf("%lld",&n)!=EOF)
{
i=j=t=1;
for(k=0;k<n-1;k++)
{
t=i+j;j=i;i=t;
}
printf("%lld\n",t);
}
return 0;
}</span>