从Leetcode87--扰乱字符串说说动态规划与递归

从Leetcode87–扰乱字符串说说动态规划与递归


前言

从Leetcode87–扰乱字符串说说动态规划与递归


一、Leetcode87

递归求解Leetcode87

#参考负雪明烛的写法
import functools
class Solution:

    #记忆化递归
    @functools.lru_cache(None)
    #将字符串分为左右两部分
    #s1[0:i]和 s2[N - i:N]作为左子树,s1[i:N]和 s2[0:N-i]作为右子树
    def isScramble(self, s1: str, s2: str) -> bool:
        N =len(s1);
        if N==0:
            return  True;
        if N==1:
            return s1==s2;
        if sorted(s1)!= sorted(s2):
            return False;
        for i in range(1,N):
            if self.isScramble(s1[:i],s2[:i]) and self.isScramble(s1[i:],s2[i:]):
                return True;
            if self.isScramble(s1[:i],s2[N-i:]) and self.isScramble(s1[i:],s2[:N-i]):
                return True;
        return False;

二、代码解析

lru使用

lru是一种缓存算法,可以通过链式哈希表的方法实现。
哈希表中存储key到链表结点的映射,每当从链表中获取某个节点时,实际上是从哈希表中获取该节点,然后修改链表,使得当前获取的节点插入链表头。
被 lru_cache 装饰的函数会有 cache_clear 和 cache_info 两个方法,分别用于清除缓存和查看缓存信息。

  @functools.lru_cache(None)

代码如下(示例):

from functools import lru_cache

@lru_cache(None)
def add(x, y):
    print("calculating: %s + %s" % (x, y))
    return x + y

print(add(1, 2))
#当第二次调用 add(1, 2) 时,并没有真正执行函数体,而是直接返回缓存的结果。
print(add(1, 2))
print(add(2, 3))

实际上, python在递归函数上调用lru_cache,就是强行将递归算法向动态规划算法方向优化。

三、对递归和动态规划的一些思考

在和小麦先生的讨论中,我们交换了对递归算法以及动态规划算法的理解。
动态规划是复用计算量的递归。

假设一个问题的解决需要若干步,第一步走完之后会出现n种结果。同样第二步从n种结果中选出一种解法,又出现m种结果。如果我们换个角度看问题,第一步确实只有一种走法,第二步有n种解法,但是第三步实际上也只有m种解法。第二步不同的解法虽然造成了不同后果,但是都在m种最终解法的范围内。假如第三步以及之后的步骤造成的影响,不受第二步所影响,那么我们就可以把第三步的m种选择造成的影响给记录下来。m种选择造成的影响是没法完全记录下来的,如果完全记录下来就变成穷举了,但如果只把最好结果或最坏结果,或者几种结果记录下来。问题就变成从后往前解决,也即是自底向上的动态规划算法。

以最简单的动态规划算法–斐波那契数列为例,如果需要计算f(5),我们需要先计算f(4)和f(3),而f(4)和f(3)分别要算f(3),f(2)和f(2),f(1)。所以,递归重复算了2次f(4),3次f(3),2次f(2)。而动态规划算法将复用计算结果,大大减少计算量。 ---- 小麦先生

在编者看来,递归和动态规划算法是很相似的。递归和动态规划算法都是将问题分解为若干子问题,动态规划子问题之间的关系可以通过某种数学表达,而递归算法是直接分解调用子问题。 -----kingsley

总结

我们从Leetcode87–扰乱字符串问题入手,从lru_cache函数出发,谈一谈对于动态规划与递归算法一些较为浅显的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值