Leetcode Minimum ASCII Delete Sum for Two Strings

来源:互联网 发布:windows nginx php 编辑:程序博客网 时间:2024/06/08 10:02

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