子序列——换个马甲的LCS(六)

LeetCode_72_EditDistance

题目分析:

本质还是LCS。回忆这三个题走来。
1.最长公共子序列。
2.Ascii值最大公共子序列。
3."消耗"最小公共子序列。
dp[i][j] 代表将s1 0 到 i - 1 和 s2 0 到 j - 1 完成"转换"的最小消耗
if(s1[i - 1] == s2[j - 1])//相同 无消耗
  dp[i][j] = dp[i - 1][j - 1];
else
  dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
上方三个式子的意义
dp[i - 1][j]左边少一个 要多增1
dp[i][j - 1]右边多一个 要多删1
dp[i - 1][j - 1]左右都少一个 要多变1
初始项易得
dp[0][j] = j;
dp[i][0] = i;

解法一:循环

public static int minDistance(String word1, String word2) {
    int n1 = word1.length(), n2 = word2.length();
    int dp[][] = new int[n1 + 1][n2 + 1];
    for (int i = 0; i <= n1; ++i) dp[i][0] = i;
    for (int i = 0; i <= n2; ++i) dp[0][i] = i;
    for (int i = 1; i <= n1; ++i) {
        for (int j = 1; j <= n2; ++j) {
            if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
            }
        }
    }
    return dp[n1][n2];
}

解法二:递归

/**
 * 递归写法 更容易看出方程中三个项的意义
 */
public static int minDistance2(String word1, String word2) {
    if (word1.equals("") || word2.equals("")) {
        return Math.max(word1.length(), word2.length());
    }
    int dp[][] = new int[word1.length()][word2.length()];
    for (int i = 0; i < word1.length(); i++) {
        for (int j = 0; j < word2.length(); j++) {
            dp[i][j] = -1;
        }
    }
    minDistance(word1.toCharArray(), 0, word2.toCharArray(), 0, dp);
    return dp[0][0];
}

private static int minDistance(char[] word1, int i, char[] word2, int j, int[][] dp) {
    if (i == word1.length || j == word2.length) {
        return Math.max(word1.length - i, word2.length - j);
    }
    if (dp[i][j] >= 0) {
        return dp[i][j];
    }
    int d = 0;
    if (word1[i] == word2[j]) {
        d = minDistance(word1, i + 1, word2, j + 1, dp);

    } else {
        int replace = minDistance(word1, i + 1, word2, j + 1, dp);
        int del = minDistance(word1, i + 1, word2, j, dp);
        int insert = minDistance(word1, i, word2, j + 1, dp);
        d = Math.min(Math.min(replace, del), insert) + 1;
    }
    dp[i][j] = d;
    return d;
}

你可能感兴趣的:(子序列——换个马甲的LCS(六))