Copy Input: s1 = "sea", s2 = "eat"
Output: 231
Explanation: Deleting "s" from "sea" adds the ASCII value of "s" (115) to the sum.
Deleting "t" from "eat" adds 116 to the sum.
At the end, both strings are equal, and 115 + 116 = 231 is the minimum sum possible to achieve this.
Copy 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.
Copy // 备忘录
int memo[][];
/* 主函数 */
int minimumDeleteSum(String s1, String s2) {
int m = s1.length(), n = s2.length();
// 备忘录值为 -1 代表未曾计算
memo = new int[m][n];
for (int[] row : memo)
Arrays.fill(row, -1);
return dp(s1, 0, s2, 0);
}
// 定义:将 s1[i..] 和 s2[j..] 删除成相同字符串,
// 最小的 ASCII 码之和为 dp(s1, i, s2, j)。
int dp(String s1, int i, String s2, int j) {
int res = 0;
// base case
if (i == s1.length()) {
// 如果 s1 到头了,那么 s2 剩下的都得删除
for (; j < s2.length(); j++)
res += s2.charAt(j);
return res;
}
if (j == s2.length()) {
// 如果 s2 到头了,那么 s1 剩下的都得删除
for (; i < s1.length(); i++)
res += s1.charAt(i);
return res;
}
if (memo[i][j] != -1) {
return memo[i][j];
}
if (s1.charAt(i) == s2.charAt(j)) {
// s1[i] 和 s2[j] 都是在 lcs 中的,不用删除
memo[i][j] = dp(s1, i + 1, s2, j + 1);
} else {
// s1[i] 和 s2[j] 至少有一个不在 lcs 中,删一个
memo[i][j] = Math.min(
s1.charAt(i) + dp(s1, i + 1, s2, j),
s2.charAt(j) + dp(s1, i, s2, j + 1)
);
}
return memo[i][j];
}
Another Version:
class Solution {
public int minimumDeleteSum(String s1, String s2) {
String lcs = getLongestCommonSeq(s1, s2);
int result1 = 0, result2 = 0;;
int left = 0; int right = 0;
while(left< s1.length() && right < lcs.length())
{
if(s1.charAt(left) == lcs.charAt(right))
{
right++;
}
else
{
result1 += (int)s1.charAt(left);
}
left++;
}
while(left < s1.length())
{
result1 += s1.charAt(left);
left++;
}
while(right < lcs.length())
{
result1 += lcs.charAt(right);
right++;
}
left = 0; right = 0;
while(left< s2.length() && right < lcs.length())
{
if(s2.charAt(left) == lcs.charAt(right))
{
left++;
right++;
}
else
{
result2 += (int)s2.charAt(left);
left++;
}
}
while(left < s2.length())
{
result2 += s2.charAt(left);
left++;
}
while(right < lcs.length())
{
result2 += lcs.charAt(right);
right++;
}
return result1 + result2;
}
public String getLongestCommonSeq(String s1, String s2)
{
int l1 = s1.length();
int l2 = s2.length();
String[][] dp = new String[l1+1][l2+1];
for(int i = 0; i<=l1; i++)
{
dp[i][0] = "";
}
for(int i = 0; i<= l2; i++)
{
dp[0][i] = "";
}
for(int i = 1; i<=l1; i++)
{
for(int j = 1; j<=l2; j++)
{
if(s1.charAt(i-1) == s2.charAt(j-1))
{
dp[i][j] = new StringBuilder(dp[i-1][j-1]).append(s1.charAt(i-1)).toString();
}
else
{
dp[i][j] = getMaxString(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[l1][l2];
}
public String getMaxString(String s1, String s2)
{
if(s1.length() == s2.length())
{
int result1 = 0; int result2 = 0;
for(int i = 0; i< s1.length(); i++)
{
result1 += (int) s1.charAt(i);
result2 += (int) s2.charAt(i);
}
if(result1 > result2) return s1;
else return s2;
}
return s1.length() > s2.length() ? s1 : s2;
}
}