Leetcode Minimum ASCII Delete Sum for Two Strings

22 篇文章 0 订阅

Input: s1 = “delete”, s2 = “leet”
Output: 403
Explanation: Deleting “dee” from “delete” to turn the string into “let”, adds 100[d]+101[e]+101[e] to the sum. Deleting “e” from “leet” adds 101[e] to the sum. At the end, both strings are equal to “let”, and the answer is 100+101+101+101 = 403.
If instead we turned both strings into “lee” or “eet”, we would get answers of 433 or 417, which are higher.

这道题要求在剩余子序列相同的条件下删除字符的ASCII之和最小,并返回最小的ASCII之和。其实是求两个数组的最长公共子序列问题的变体。后者是动态规划的基本问题。

首先先回顾一下动态规划问题的求解方法。
动态规划问题的求解需要确定两点:
1. 状态是什么(状态的定义)
2. 状态如何转移(状态转移方程的定义)

那么考虑如何求两个数组的最长公共子序列的长度。最长公共子序列的长度即为状态,即dp[i][j]中存储值;
状态转移情况分两种:当s1[i]与s2[j]相等时,当前状态为dp[i-1][j-1]+1; 当s1[i]与s2[j]不等时,应返回dp[i-1][j]和dp[i][j-1]中的最大值。

故C++程序为:

class Solution {
public:
    int minimumCommonSubsequenceLength(string s1, string s2) {
    int len1 = s1.size(), len2 = s2.size();
    vector<vector<int>> dp(len1+1, vector<int>(len2+1, 0));
    for(int i=1; i<=len1; i++)
    {
        for(int j=1; j<=len2; j++)
        { 
            if(s1[i-1]==s2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
              else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
        }   
    }
    return dp[i][j];
    }
};    

再考虑如何解决使删除的ASCII和最小的问题。有两种方法:
1. 在求解最长公共子序列的基础上先计算两字符串的ASCII总和,再根据得到的字符串长度,求取剩余量即可。需注意的是:当两字符相等时,需由原来的dp[i][j] = dp[i-1][j-1] + 1 变为 dp[i][j] = dp[i-1][j-1] + s1[i-1];
2. 重新定义状态,及原始状态为两字符串的ASCII之和,最后直接返回dp[len1][len2]即可。

代码如下:
方法一

class Solution {
public:
    int minimumDeleteSum(string s1, string s2) {

        int len1 = s1.size(), len2 = s2.size(), sum = 0;
        vector<vector<int>> dp(len1+1, vector<int>(len2+1, 0));

        for(int i=0; i<len1; i++)      sum += s1[i];
        for(int j=0; j<len2; j++)      sum += s2[j];

        for(int i=1; i<=len1; i++)
        {
            for(int j=1; j<=len2; j++)
            {
                if(s1[i-1]==s2[j-1])  dp[i][j] = dp[i-1][j-1] + s1[i-1];
                else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
        return sum - 2*dp[len1][len2];
    }
};

方法二

class Solution {
public:
    int minimumDeleteSum(string s1, string s2) {

        int len1 = s1.size(), len2 = s2.size(), sum = 0;

        for(int i=0; i<len1; i++)      sum += s1[i];
        for(int j=0; j<len2; j++)      sum += s2[j];

        vector<vector<int>> dp(len1+1, vector<int>(len2+1, sum));

        for(int i=1; i<=len1; i++)
        {
            for(int j=1; j<=len2; j++)
            {
                if(s1[i-1]==s2[j-1])  dp[i][j] = dp[i-1][j-1] - 2*s1[i-1];
                else dp[i][j] = min(dp[i-1][j], dp[i][j-1]);
            }
        }
        return dp[len1][len2];
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值