控制文件夹递归深度_教女朋友递归与记忆化递归

最近惹女朋友生气了,写一篇技术文章来安抚她~

说起递归,我们最开始想到的就是斐波那契数列,这道题十分的经典,代码如下:

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

递归结构最常用在树结构中,例如先序遍历等等。

其次用在回溯法中,递归可以撤销之前的操作。

同时递归还是动态规划的一种超集,其名为记忆化递归。

如果你刷题的过程中经常会头疼动态规划类型的题,那么这篇文章正适合你!

因为记忆化递归在很多场景下可以替换动态规划,其coding的难度要小于动态规划。

那么为什么要记忆化递归?什么是记忆化递归呢?

为什么记忆化递归?

回答:因为普通的递归可能会重复求解某一值,类似斐波那契数列。同样的子问题可能会被求解多次,这样就会很慢很慢很慢。

解决方法:我们把历史求解(子问题)记录下来,如果下次需要求解子问题,那么直接取出就好。其时间复杂度为O(1)。

下面的代码就是记忆化递归来求解斐波那契数列~

m = [0] * max_size # 开辟一个数组来存储,或者使用字典
def f(n):
    if n <= 1:
        return n
    if not m[n]:
        m[n] = f(n - 1) + f(n -2)
    return m[n]


记忆化递归的问题求解模板

ae61367e45cce077ccd1aec04cf34af9.png
红色区域是边界区域。蓝色区域是为了求解子问题。绿色区域是当问题求结果,则直接返回。

记忆化递归相比动态规划的优势在哪儿?

动态规划是有先后顺序的,子问题求解后才能求解父问题。因此你要小心确保问题求解的顺序,从而避免bug。

但是记忆化递归,当你的子问题没有求解时,程序会自动去求解。而不需要小心翼翼的去确保顺序,减轻我们的工作量。

记忆化递归相比动态规划的劣势在哪儿?

因为动态规划时有先后顺序的,因此实际上有一些求解的子问题用不到了可以将空间释放掉。

而记忆化递归再这种优化上就很难。

故记忆化递归可能在空间复杂度上比不上精心设计的动态规划。

但是!!!这里是精心设计的动态规划,为了精心设计,我们可能会花很长的时间去写控制规则,为了减少那么一丢丢的内存。但是实际上我们刷题,失败的原因往往是超时!!!而不是超出内存限制。

因此记忆化递归用于刷题还是挺舒服的~


2019/07/15

记忆化递归的一个缺点是,有可能会超越python的最大递归深度。

eb3296f995493394b4f35f8cab8d2f3e.png
牛客网上的一道题,会超越递归的深度
最少数量货物装箱问题_牛客网​www.nowcoder.com
x = int(input())

m = [0] * (x + 1)
MAXVALUE = 100000000
def func(x):
    if x < 3 :
        return MAXVALUE
    elif x == 3 or x == 5 or x == 7:
        return 1
    if not m[x]:
        t = min(func(x - 3), func(x - 5), func(x - 7))
        if t == MAXVALUE:
            m[x] = t
        else:
            m[x] = t + 1
    return m[x]

t = func(x)
if t == MAXVALUE:
    print(-1)
else:
    print(t)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值