斐波那契数列、青蛙跳台阶、矩形覆盖

参考:https://yq.aliyun.com/articles/664969
三道题都是找规律

斐波那契数列

在这里插入图片描述

  1. 最基本的方法(运用递归)

这个解法是最基本的方法,但是存在很严重的效率问题。

用树形结构图来分析的话,你会发现很多重复的结点。而重复的结点数会随着n的增大而急剧增加,这就意味着计算量会随着n的增大而急剧增大,导致时间变得巨长无比。

  1. 优化后的方法

其实改进的方法并不复杂,只需要避免1.最基本方法中的重复计算即可。

所以,我们可以把已经得到的数列中间项保存起来,如果下次需要计算的时候,先查找一下,如果已经计算过,就不用重复计算了。

当然,更简单的方法是,自下而上计算,首先根据f(0) 和f(1)算出f(2),再根据f(1)和f(2)算出f(3)……依此类推,可以算出第n项。

那么,自然的,这种时间复杂度便是O(n)。

def Fibonacci(self, n):
        # write code here
        res = [0,1]
        if n < len(res): #n从0开始
            return res[n]
            
        c = 0
        for i in range(2, n+1):
            c = res[-2] + res[-1]
            res[-2], res[-1] = res[-1], c
        return c

跳台阶

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

分析如下:

假如现在台阶只有 1 级,n = 1,那么这只青蛙就在只有 1 种跳法:1(1 代表一次跳 1 级台阶)也就是 f(1) = 1 种跳法
假如现在台阶只有 2 级,n = 2,那么这只青蛙可以有 2 种跳法:1 1、2(1 代表一次跳 1 级台阶,2 代表一次跳 2 级台阶),也就是 f(2) = 2 种跳法
假如现在台阶有 3 级,n = 3,青蛙可以有几种跳法呢?
假如青蛙先跳了 1 级台阶,还剩下 2 级台阶,那它还有几种跳法呢?通过第 2 个情况分析知道有 2 种跳法即f(2);假如青蛙先跳了 2 级台阶,根据第 1 个情况分析知道有 1 种跳法即f(1),所以这时候得出 f(3) = f(2) + f(1) 种方法
假如现在台阶有 4 级,n = 4,我们利用上面的规律继续分析可得:f(4) = f(3) + f(2)
综上所述,我们得出其实这个算法就是一个(变形)斐波那契数列问题,公式如下:

n = 1, f(1) = 1
n = 2, f(2) = 2
n > 2, f(n) = f(n -1) + f(n -2)
所以至此明白了,青蛙跳台阶问题就是一个(变形)斐波那契数列问题。

    def jumpFloor(number):
        # write code here
        res = [1,2]
        if number <= len(res): #n从1开始,故后面减一
            return res[number-1]

        c = 0
        for i in range(3, number+1):
            c = res[-1] + res[-2]
            res[-2], res[-1] = res[-1], c

        return c

变态跳台阶

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

分析如下:

假如现在台阶只有 1 级,n = 1,那么这只青蛙就在只有 1 种跳法:1(1 代表一次跳 1 级台阶)也就是 f(1) = 1 种跳法
假如现在台阶只有 2 级,n = 2,那么这只青蛙可以有 2 种跳法:1 1、2(1 代表一次跳 1 级台阶,2 代表一次跳 2 级台阶),也就是 f(2) = 2 种跳法
假如现在台阶有 3 级,n = 3,青蛙可以有几种跳法呢?
假如青蛙先跳了 1 级台阶,还剩下 2 级台阶,那它还有几种跳法呢?通过第 2 个情况分析知道有 2 种跳法即f(2);假如青蛙先跳了 2 级台阶,根据第 1 个情况分析知道有 1 种跳法即f(1);最后,青蛙可以一下子跳3级台阶,是1种跳法,所以这时候得出 f(3) =f(3)+ f(2)+f(1)+1 =4种方法
假如现在台阶有 4 级,n = 4,我们利用上面的规律继续分析可得:f(4) = f(3) + f(2) +f(1) + 1 = 8
综上所述,我们得出其实这个算法就是一个(变形)斐波那契数列问题,公式如下:

n = 1, f(1) = 1
n = 2, f(2) = 2
n > 2, f(n) = f(n -1) + f(n -2) + …+f(1) + 1
又,f(n-1) = f(n-2) + f(n-3) +…+f(1) + 1
两式相减,可得f(n) = 2f(n-1) 是个等比数列,而且初项为1

    def jumpFloorII(self, number):
        # write code here
        return pow(2, number-1)

矩形覆盖

我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
分析:
当n=1时,矩形大小2x1,小矩形只有竖着覆盖一种方法f(1) = 1;
当n=2时,矩形2x2,小矩形可以横着覆盖,也可以竖着覆盖,则有2种方法f(2) = 2
当n=3时,矩形2x3,第一个矩形竖着覆盖,则剩下一个2x2的矩形有f(2)=2种覆盖方法,如果第一个矩形横着覆盖,则剩下矩形只有一覆盖方法,所以f(3)=f(2) + f(1)
当n=4时,矩形2x4,如果第一个矩形竖着覆盖,则剩下2x3矩形有f(3)种覆盖方法,如果第一个矩形为横着覆盖,则剩下一个1x2,一个2x2,有f(2)种覆盖方法,故f(4) = f(3) + f(2)
因此,本题和青蛙跳台阶问题的规律一样
n = 1, f(1) = 1
n = 2, f(2) = 2
n > 2, f(n) = f(n -1) + f(n -2)

    def rectCover(self, number):
        # write code here
        res = [0,1,2]
        if number < len(res):
            return res[number]

        c = 0
        for i in range(3, number + 1):
            c = res[-2] + res[-1]
            res[-2], res[-1] = res[-1], c

        return c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值