剑指offer——斐波那契数列相关问题总结

题目一:写一个函数,输入n,求斐波那契数列的第n项。斐波那契数列定义如下:


                                                             
分析:递归,效率很低的解法
long long Fabonacci(unsigned int n)
{
	if(n<=0)
		return 0;
	if(n==1)
		return 1;
	return Fabonacci(n-1)+Fabonacci(n-2);
}
分析:简单的迭代方法,从下往上计算,首先根据f(0)和f(1)计算出f(2),再根据f(1)和f(2)计算出f(3)……以此类推。很容易理解,时间复杂度是O(n)
long long Fabonacci2(unsigned n)
{
	int result[2]={0,1};
	if(n<2)
		return result[n];
	long long currOne=0;
	long long currTwo=1;
	long long r;
	for(int i=2;i<=n;++i)
	{
		r=currOne+currTwo;
		currOne=currTwo;
		currTwo=r;
	}
	return r;
}


题目二:一只青蛙一次可以跳上1级台阶,也以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分析:
以看做斐波那契问题。如果只有1级台阶,只有一种情况。如果有2级台阶,则有两种方法:一次是分两次跳,每次跳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)。所以答案同上,上面写法只保存了技术为n的方法数,如果想保存1到n的方法,程序如下。
int jumpFloor(int number)
{
    if(number<=1)
        return 1;
    if(number==2)
        return 2;
    vector <int>result(number+1,0);
    result[1]=1;
    result[2]=2;
    for(int i=3;i<number+1;i++)
        result[i]=result[i-1]+result[i-2];
    return result[number];
}


题目三:矩形覆盖:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
分析:
假设现在是有8个2*1的小矩形去覆盖一个2*8的大矩形。我们把覆盖方法数记为f(8)。用第一个1*2的小矩形去覆盖大矩形的最左边有两个选择,竖着放或者横着放。当竖着放的时候,右边还剩下2*7的区域,这种情况下的覆盖方法是f(7)。接下来考虑横着放的情况。当用1*2的小矩形横着放在左上角的时候,左下角必须横着放一个1*2的小矩形,而在右边还剩下2*6的区域,这种情况下的覆盖方法记为f(6)。
因此f(8)=f(7)+f(6)。可以看出,这仍然是斐波那契数列。

题目四:疯狂跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分析:
假设现在n=10,方法数记为f(10)。如果第一下跳了1级,那么剩下的方法为f(9),如果第一下跳了2级,那么剩下的方法是f(8),依次类推……,如果第一下跳了9级那么剩下的方法是f(1),如果第一下就直接跳上10级,那么就只有一种方法。
因此,f(10)=f(9)+f(8)+f(7)+f(6)+f(5)+f(4)+f(3)+f(2)+f(1)+1;
刚开始f(1)=1,f(2)=2。
程序见下:
int jumpFloorII(int number)
{
    if(number<=1)
        return 1;
    if(number==2)
        return 2;
    vector<int>result(number+1,0);
    result[1]=1;
    result[2]=2;
    for(int i=3;i<=number;i++)
    {
        {
          for(int j=1;j<i;j++)
              result[i]+=result[j];
        }
        result[i]+=1;
    }
    return result[number];
}

转载请注明出处:http://blog.csdn.net/xingyanxiao/article/details/47055973
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值