剑指offer 14 19 题解

剑指 Offer 14- I. 剪绳子

动态规划解法

状态: dp[n] = n米的最大乘积

递推: dp[i] = max([max(dp[k], k) * max(dp[i-k], i-k) for k in range(i//2+1)])

初始化 all set 0 dp[1]=0 dp[2] = 1

class Solution:
    def cuttingRope(self, n: int) -> int:
        # 状态: dp[n] = n米的最大乘积
        # 递推: dp[i] = max([max(dp[k], k) * max(dp[i-k], i-k) for k in range(i//2+1)])
        # 初始化 all set 0 dp[1]=0 dp[2] = 1
        dp = [0] * (n+1)
        dp[2] = 1
        for i in range(3, n+1):
            dp[i] = max([max(dp[k], k) * max(dp[i-k], i-k) for k in range(i//2+1)])
        return dp[n]

数学解析:

class Solution:
    def cuttingRope(self, n: int) -> int:
        if n <= 3: return n - 1
        a, b = n // 3, n % 3
        if b == 0: return int(math.pow(3, a))
        if b == 1: return int(math.pow(3, a - 1) * 4)
        return int(math.pow(3, a) * 2)

剑指 Offer 19. 正则表达式匹配

状态: dp[i, j]表示s[:i], p[:j]的匹配情况

如果正则p为空,除非字符串s也为空,否则都是False

递推一下,求dp[i, j]

  1. 如果 s [ i ] = p [ j ] s[i] = p[j] s[i]=p[j]字母,且相同,则 d p [ i , j ] = d p [ i − 1 , j − 1 ] dp[i,j] = dp[i-1,j-1] dp[i,j]=dp[i1,j1]

  2. 如果 p [ j ] = ′ . ′ p[j] = '.' p[j]=.,则无所谓 s [ i ] s[i] s[i]是什么, d p [ i , j ] = d p [ i − 1 , j − 1 ] dp[i,j] = dp[i-1,j-1] dp[i,j]=dp[i1,j1]

  3. 如果 p [ j ] = ′ ∗ ′ p[j]='*' p[j]=,则又要分情况讨论:

    情况1: 重复0次,则p的最后两个字母 c ∗ c* c可以被丢弃, d p [ i , j ] = d p [ i , j − 2 ] dp[i,j] = dp[i,j-2] dp[i,j]=dp[i,j2]

    情况2: 重复1次或者1次以上,则如果 s [ i ] s[i] s[i] p [ j ] p[j] p[j]可以匹配,则少重复一遍也可以被匹配上, 所以如果有 s [ i ] = p [ j − 1 ] s[i]=p[j-1] s[i]=p[j1], 则有 d p [ i , j ] = d p [ i , j − 1 ] dp[i,j] = dp[i,j-1] dp[i,j]=dp[i,j1]

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        # 状态: dp[i, j]表示s[:i], p[:j]的匹配情况
        n = len(s)
        m = len(p)
        dp = [[False] * (m+1) for _ in range(n+1)]
        
        for i in range(n+1): # 字符串s
            for j in range(m+1): # 正则式p
                if j == 0: # 空正则
                    dp[i][j] = (i==0)
                else:
                    if i >= 1 and (s[i-1] == p[j-1] or p[j-1] == '.'): # 情况1,2合并
                        dp[i][j] = dp[i-1][j-1]
                    if p[j-1] == '*':
                        if j>=2 and dp[i][j-2]: # 情况3.1
                            dp[i][j] = True
                        else: # 情况3.2
                            if (j>=2 and i>=1 and p[j-2] == s[i-1]) or p[j-2] == '.' :
                                dp[i][j] = dp[i-1][j]
        return dp[n][m]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值