快速理解算法之动态规划

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解。
ok,这是百度百科给出的定义。这个定义写的太过抽象,我反正是看不懂。
在这里插入图片描述
虽然我觉得你们个个专业 英语八级,但是为了卖弄我的英语水平,我还是翻译一下
Those who cannot remember the past are condemned to repeat it. - George Santayana
“不能铭记历史的人注定要重蹈覆辙。”

writes down “1+1+1+1+1+1+1+1 =” on a sheet of paper
“What’s that equal to?”
counting “Eight!”
writes down another “1+” on the left
“What about that?”
quickly “Nine!”
“How’d you know it was nine so fast?”
“You just added one more”
“So you didn’t need to recount because you remembered there were eight! Dynamic Programming is just a fancy way to say ‘remembering stuff to save time later’”.

A “1+1+1+1+1+1+1+1 =?” *
A : “上面等式的值是多少”
B : 计算 “8!”
A 在上面等式的左边写上 “1+” *
A : “此时等式的值为多少”
B : quickly “9!”
A : “你怎么这么快就知道答案了”
A : “只要在8的基础上加1就行了”
A : “所以你不用重新计算因为你记住了第一个等式的值为8!动态规划算法也可以说是 ‘记住求过的解来节省时间’”

以上两段即可阐述动态规划的核心思想了:记住已经解决的子问题的解。

按照定义说的,动态规划是将大问题分解成子问题。这个定义当然没有任何毛病,但这肯定不是动态规划的核心思想呀。我就问:什么大问题不能分解成多个子问题?
关键在于:记住这些小问题的解。
我举个简单的例子。
小明爬楼梯(小明脑子一定是有问题的),他要爬十层楼梯。那么请问他一共有几种爬上去的办法呢(假设其每次可跨一层或者二层楼梯)?
在这里插入图片描述
你看着图,我们就把问题转化成了0走到10有几种走法了嘛
我就问:如果我们计算了7到10的走法,路径数是不是就可以保存下来。不管5走过来还是6走过来,7到10的走法是通用的对吧。这就是问题的本质了。计算后保存而不是重复计算。
ok,talk is cheap,show me the code。
让我们刷题leetcode冷静一下

给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符。
'*' 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s) ,而不是部分字符串。
说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:

输入:
s = "aa"
p = "a*"
输出: true
解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。
示例 3:

输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:

输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。
示例 5:

输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        dp=[[False  for i in range(len(p)+1)] for j in range(len(s)+1)]
        dp[0][0]=True
        for j in range(1,len(p)+1):
            dp[0][j]=((j>=2) and dp[0][j-2] and p[j-1]=="*")#s是空串的情况
        for i in range(1,len(s)+1):
            for j in range(1,len(p)+1):
                    if p[j-1]=='*':
                        dp[i][j]=dp[i][j-2] or (dp[i-1][j] and(s[i-1]==p[j-2] or p[j-2]==".")) 
                    else:
                        dp[i][j]=dp[i-1][j-1] and (s[i-1]==p[j-1] or p[j-1]==".")
        return dp[len(s)][len(p)]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值