剑指offer——斐波那契之跳台阶以及变态跳台阶及矩形覆盖的一般形态总结

一、题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

解题思想:

1.找规律:

台阶数:1  2  3  4  5   6   7

跳法:   1  2  3  5  8  13  21

只看跳法的变化就可以看出f(n)=f(n-1)+f(n-2)

2.假如n个台阶有f(n)种方法

最后一步可以是跳了一个台阶,则有f(n-1)种方法

最后一步也可以是跳了两个台阶,则有f(n-2)种方法

当有一个台阶的时候有1种方法

当有两个台阶的时候有2种方法

f(n)=f(n-1)+f(n-2)

2种解题方法

 1.递归实现:

class Solution {
public:
    int jumpFloor(int number) {
    	if(number==0)
    	{
    		return 0;
		}
		if(number==1)
		{
			return 1;
		}
		if(number==2)
		{
			return 2;//11,2
		}

        else{
        	return (jumpFloor(number-1)+jumpFloor(number-2));
		}
       
    }
};

 2.非递归实现:

class Solution {
public:
    int jumpFloor(int number) {
    	if(number==0)
    	{
    		return 0;
		}
		if(number==1)
		{
			return 1;
		}
		if(number==2)
		{
			return 2;//11,2
		}

		int a=1,b=2,c=0;
        for(int i=3;i<=number;i++)
        {
        	c=a+b;
        	a=b;
        	b=c;
		}
       return c;
    }
};

二、题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

解题思想:

1.找规律:

台阶数:1  2  3  4  5 

跳法:   1  2  4  8  16 

只看跳法的变化就可以看出f(n)=2*f(n-1)

2.因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
所以f(n)=f(n-1)+f(n-2)+...+f(1)
因为f(n-1)=f(n-2)+f(n-3)+...+f(1)

所以f(n)=2*f(n-1)

3.每个台阶都有跳与不跳两种情况(除了最后一个台阶),比如一个台阶不跳记为0,跳记为1,则有几个台阶,就有几位的0或1,n位二进制码可表示2^n个数,而最后一个台阶必须跳,所以共用2^(n-1)中情况

2种解题方法

 1.非递归实现:

 

class Solution {
public:
    int jumpFloorII(int number) {
    	int c=1;
		while(--number)
        {
            c*=2;
        }
		return c;
    }
};

 

2.递归实现

class Solution {
public:
    int jumpFloorII(int number) {
        int count = 0;
         
        if(number == 0)
            return 1;
         
        for(int i =1; i<=number;++i){
            count += jumpFloorII(number-i);
        }
         
        return count;
    }
};

 

三、题目描述

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

class Solution {
public:
    int rectCover(int number) {
    	int i=0;
    	if(number==1)
    	{
    		return 1;
		}
		if(number==2)
		{
			return 2;
		}
		if(number==3)
		{
			return 3;
		}
		int a=2,b=3,c=0;
		for(i=4;i<=number;i++)
		{
			c=a+b;
			a=b;
			b=c;
		}
		//return rectCover(number-1)+rectCover(number-2);
		return c;
    }
}; 

分析摘自DanielLea的牛客讨论:https://www.nowcoder.com/profile/2951934/codeBookDetail?submissionId=16796833

思路分析:

痛定思痛,还是不能够贪小便宜。用归纳法归纳如下,

(1)当 n < 1时,显然不需要用2*1块覆盖,按照题目提示应该返回 0。

(2)当 n = 1时,只存在一种情况。

(3)当 n = 2时,存在两种情况。

(4)当 n = 3时,明显感觉到如果没有章法,思维难度比之前提升挺多的。

... 尝试归纳,本质上 n 覆盖方法种类都是对 n - 1 时的扩展。

可以明确,n 时必定有 n-1时原来方式与2*1的方块结合。也就是说, f(n) = f(n-1) + ?(暂时无法判断)。

(4)如果我们现在归纳 n = 4,应该是什么形式?

4.1)保持原来n = 3时内容,并扩展一个 2*1 方块,形式分别为 “| | | |”、“= | |”、“| = |”

4.2)新增加的2*1 方块与临近的2*1方块组成 2*2结构,然后可以变形成 “=”。于是 n = 4在原来n = 3基础上增加了"| | ="、“= =”。

再自己看看这多出来的两种形式,是不是只比n = 2多了“=”。其实这就是关键点所在...因为,只要2*1或1*2有相同的两个时,就会组成2*2形式,于是就又可以变形了。

所以,自然而然可以得出规律: f(n) = f(n-1) + f(n-2), (n > 2)。

 

如果看了这一套理论还存在疑惑。可以尝试将题目改成1*3方块覆盖3*n、1*4方块覆盖4*n。

相应的结论应该是:

(1)1 * 3方块 覆 盖3*n区域:f(n) = f(n-1) + f(n - 3), (n > 3)

(2) 1 *4 方块 覆 盖4*n区域:f(n) = f(n-1) + f(n - 4),(n > 4)

更一般的结论,如果用1*m的方块覆盖m*n区域,递推关系式为f(n) = f(n-1) + f(n-m),(n > m)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值