leetcode - 712 两个字符串的最小ASCII删除和

  1. 两个字符串的最小ASCII删除和
    给定两个字符串s1, s2,找到使两个字符串相等所需删除字符的ASCII值的最小和。

示例 1:

输入: s1 = “sea”, s2 = “eat”
输出: 231
解释: 在 “sea” 中删除 “s” 并将 “s” 的值(115)加入总和。
在 “eat” 中删除 “t” 并将 116 加入总和。
结束时,两个字符串相等,115 + 116 = 231 就是符合条件的最小和。
示例 2:

输入: s1 = “delete”, s2 = “leet”
输出: 403
解释: 在 “delete” 中删除 “dee” 字符串变成 “let”,
将 100[d]+101[e]+101[e] 加入总和。在 “leet” 中删除 “e” 将 101[e] 加入总和。
结束时,两个字符串都等于 “let”,结果即为 100+101+101+101 = 403 。
如果改为将两个字符串转换为 “lee” 或 “eet”,我们会得到 433 或 417 的结果,比答案更大。
注意:

0 < s1.length, s2.length <= 1000。
所有字符串中的字符ASCII值在[97, 122]之间。

在这里插入图片描述

思路:
从做后一个元素开始删除,两个元素相等的时候,删除代价是0。
否则选择其中一个删除,这样就形成了类似于二叉树的递归结构。递归结构可以转换成DP

在这里插入图片描述

# 递归的写法


class Solution:
    def minimumDeleteSum(self, s1: str, s2: str) -> int:

        memory = [[0]*(len(s1)+1) for _ in range(len(s2)+1)]

        def dp(str_01: list, str_02: list):
            len_str_01 = len(str_01)
            len_str_02 = len(str_02)

            if len_str_01 == 0 and len_str_02 == 0:  # s1 is 空
                return 0

            if len_str_01 == 0:
                char = str_02.pop(-1)
                memory[len_str_01][len_str_02] = dp(str_01, str_02) + ord(char)
                return memory[len_str_01][len_str_02]

            if len_str_02 == 0:
                char = str_01.pop(-1)
                memory[len_str_01][len_str_02] = dp(str_01, str_02) + ord(char)
                return memory[len_str_01][len_str_02]

            if str_01[-1] == str_02[-1]:
                memory[len_str_01][len_str_02] = dp(str_01, str_02)
                return memory[len_str_01][len_str_02]

            # 最后一个char不相等的情况,最终的答案一定是返回较小的一个
            char01 = str_01.pop(-1)
            char02 = str_02.pop(-1)
            memory[len_str_01][len_str_02] = min(dp(str_01, str_02)+ord(char01),
                                                     dp(str_01, str_02)+ord(char02)
                                                     )
            return memory[len_str_01-1][len_str_02-1]

        return dp(list(s1), list(s2))


    def func2(self, str01:str, str02:str):
        # 方法二: 动态规划
        len_str01 = len(str01)
        len_str02 = len(str02)
        str01 = list(str01)
        str02 = list(str02)

        # 因为有一个空字符串,所以要行列都扩加1维
        dp = [[0] * (len_str01+1) for _ in range(len_str02+1)]

        # 初始化数组,处理其中一个是空字符串的情况
        for i in range(1, len_str01+1):
            char = str01[i]
            dp[0][i] = dp[0][i-1] + ord(char)
        for j in range(1, len_str02+1):
            char = str02[j]
            dp[j][0] = dp[j-1][0] + ord(char)

        for i in range(1, len_str02+1):
            for j in range(1, len_str01+1):
                if str01[j-1] == str02[i-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    char01 = str01.pop(-1)
                    char02 = str02.pop(-1)
                    dp[i][j] = min(dp[i-1][j] + ord(char01),
                                    dp[i][j-1] + ord(char02)
                                   )

        return dp[len_str02][len_str01]














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值