简单暴力到dp的优化(萌新篇)

想写一系列文章,总结一些题目,看看解决问题、优化方法的过程到底是什么样子的。

 

系列问题一:斐波那契数列问题

在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)根据定义,前十项为1, 1, 2, 3, 5, 8, 13, 21, 34, 55

问题一:

给定一个正整数n,求出斐波那契数列第n项(这时n较小)

解法一:最笨,效率最低,暴力递归,完全是抄定义。请看代码

def f0(n):
    if n==1 or n==2:
        return 1
    return f(n-1)+f(n-2)

 

分析一下,为什么说递归效率很低呢?咱们来试着运行一下就知道了

 

比如想求f(10),计算机里怎么运行的?

 

每次要计算的函数量都是指数型增长,时间复杂度O(2^(N/2))<=T(N)<=O(2^N),效率很低。效率低的原因是,进行了大量重复计算,比如图中的f(8),f(7).....等等,你会发现f(8)其实早就算过了,但是你后来又要算一遍。

如果我们把计算的结果全都保存下来,按照一定的顺序推出n项,就可以提升效率, 斐波那契(所有的一维)的顺序已经很明显了,就是依次往下求。。

优化1

def f1(n):
    if n==1 or n==2:
        return 1
    l=[0]*n
    l[0],l[1]=1,1
    for i in range(2,n):
        l[i]=l[i-1]+l[i-2]
    return l[-1]

 

时间复杂度o(n),依次往下打表就行,空间o(n).

继续优化:既然只求第n项,而斐波那契又严格依赖前两项,那我们何必记录那么多值呢?记录前两项就行了

 

优化2

def f2(n):
    a,b=1,1
    for i in range(n-1):
        a,b=b,a+b
    return a

此次优化做到了时间o(n),空间o(1)

附:这道题掌握到这里就可以了,但是其实有时间o(log2n)的方法

 

优化三:

学习过线性代数的同学们能够理解:

 

结合快速幂算法,我们可以在o(log2n)内求出某个对象的n次幂。(在其它专题详细讲解)

注意:只有递归式不变,才可以用矩阵+快速幂的方法。

注:优化三可能只有在面试上或竞赛中用,当然,快速幂还是要掌握的。

 

经过这个最简单的斐波那契,大家有没有一点感觉了?

好,我们继续往下走

(补充:pat、蓝桥杯原题,让求到一万多位,结果模一个数。

可以每个结果都对这个数取模,否则爆内存,另:对于有多组输入并且所求结果类似的题,可以先求出所有结果存起来,然后直接接受每一个元素,在表中查找相应答案)

 

问题二:

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

依旧是找递推关系,分析:跳一阶,就一种方法,跳两阶,它可以一次跳两个,也可以一个一个跳,所以有两种,三个及三个以上,假设为n阶,青蛙可以是跳一阶来到这里,或者跳两阶来到这里,只有这两种方法。它跳一阶来到这里,说明它上一次跳到n-1阶,同理,它也可以从n-2跳过来,f(n)为跳到n的方法数,所以,f(n)=f(n-1)+f(n-2)

和上题的优化二类似。

因为递推式没变过,所以可以用优化三

 

问题三:

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

请读者自己先思考一下吧。。。仔细看题。。仔细思考

如果n是1,只有一种,竖着放呗;n是2,两种:

n等于3,三种:

 

题意应该理解了吧?

读到这里,你们应该能很快想到,依旧是斐波那契式递归啊。

对于n>=3:怎么能覆盖到三?只有两种办法,从n-1的地方竖着放了一块,或者从n-2的位置横着放了两块呗。

和问题二的代码都不用变。

 

问题四:

给定一个由0-9组成的字符串,1可以转化成A,2可以转化成B。依此类推。。25可以转化成Y,26可以转化成z,给一个字符串,返回能转化的字母串的有几种?

比如:123,可以转化成

1 2 3变成ABC,

12 3变成LC,

1 23变成AW,三种,返回三,

99999,就一种:iiiii,返回一。

分析:求i位置及之前字符能转化多少种。

两种转化方法,一,字符i自己转换成自己对应的字母,二,和前面那个数组成两位数,然后转换成对应的字母

假设遍历到i位置,判断i-1位置和i位置组成的两位数是否大于26,大于就没有第二种方法,f(i)=f(i-1),想反,等于f(i-1)+f(i-2)

注意:递归式不确定,不能用矩阵快速幂

 

(这几个题放到这里就是为了锻炼找递归关系的能力,不要只会那个烂大街的斐波那契)

 

'''
斐波那契问题:
斐波纳契数列以如下被以递归的方法定义:
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
'''
#暴力抄定义,过多重复计算
def f0(n):
    if n==1 or n==2:
        return 1
    return f(n-1)+f(n-2)
#记录结果后依次递推的优化,时间O(N)
def f1(n):
    if n==1 or n==2:
        return 1
    l=[0]*n
    l[0],l[1]=1,1
    for i in range(2,n):
        l[i]=l[i-1]+l[i-2]
    return l[-1]
#既然严格依赖前两项,不必记录每一个结果,优化空间到O(1)
def f2(n):
    a,b=1,1
    for i in range(n-1):
        a,b=b,a+b
    return a

 

  • 259
    点赞
  • 245
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 111
    评论
评论 111
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兔老大RabbitMQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值