Leetcode712. 计算两个字符串删除任意字符后使二者相等的最小删除字符和

Leetcode712. Minimum ASCII Delete Sum for Two Strings

题目

Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal.

Example 1:
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.

Example 2:
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.

解题分析

这道题目非常经典,其算法思想和Edit Distance(编辑距离)的算法思想是一模一样的。我们知道,编辑距离算法采用的是一种动态规划算法的思想。
其算法的基本思想是,新建一个二维数组d,将其用来存放修改(增加或删除)当前节点使两个字符串相同的最小距离;设字符串s1的长度为l1,字符串s2的长度为l2,则二维数组的大小为(l1+1)*(l2+1)。其中初始化情况下,即二维数组其中某个下标为0的情况下,数组元素的值为前面元素的累加+1,此种情况下,即一个字符串长度为0,因此显而易见得到上面的结果。而在一般情况下,修改或增加或删除均有可能使两个字符串完全相同,因此,对应于任意一个位置,其上的元素值即为三者距离的最小值。设该位置为i,j,则有d(i,j)=min{1+d(i-1,j),1+d(i,j-1),diff(i,j)+d(i-1,j-1)},其中如果s1[i]=s2[j],则diff(i,j)=0,否则为1。
对应于这道题,初始化和公式表示有所变化,但算法思想都是一样的。很明显,在这里,初始化应该为字符串当前字符所在位置的前面所有元素之和。而d(i,j)应该变化为d(i,j)=min{s1[i-1]+d(i-1,j),s2[j-1]+d(i,j-1),diff(i,j)+d(i-1,j-1)},其中如果s1[i]=s2[j],则diff(i,j)=0,否则为s1[i-1]+s2[j-1]。最后,二维数组最后一个元素即为最小距离,就是我们最后所要返回的结果。

源代码

class Solution {
public:
    int minimumDeleteSum(string s1, string s2) {
        int i, j, size1 = s1.size(), size2 = s2.size();
        int** deleteSum = new int*[size1 + 1];
        for (i = 0; i < size1 + 1; i++) {
            deleteSum[i] = new int[size2 + 1];
        }
        for (i = 0; i < size1 + 1; i++) {
            for (j = 0; j < size2 + 1; j++) {
                deleteSum[i][j] = 0;
            }
        }
        for (i = 1; i <= size1; i++) {
            deleteSum[i][0] = deleteSum[i - 1][0] + s1[i - 1];
        }
        for (j = 1; j <= size2; j++) {
            deleteSum[0][j] = deleteSum[0][j - 1] + s2[j - 1];
        }
        for (i = 1; i <= size1; i++) {
            for (j = 1; j <= size2; j++) {
                int cost = 0;
                if (s1[i - 1] != s2[j - 1]) {
                    cost = s1[i - 1] + s2[j - 1];
                }
                deleteSum[i][j] = min(deleteSum[i - 1][j] + s1[i - 1], deleteSum[i][j - 1] + s2[j - 1]);
                deleteSum[i][j] = min(deleteSum[i][j], deleteSum[i - 1][j - 1] + cost);
            }
        }
        return deleteSum[size1][size2];
    }
};

以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~

你可能感兴趣的:(leetcode算法,leetcode)