Leetcode 编辑距离

编辑距离

题目描述:

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
  • 插入一个字符
  • 删除一个字符
  • 替换一个字符
提示:
   0 <= word1.length, word2.length <= 500
   word1 和 word2 由小写英文字母组成

题目链接

示例
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')
class Solution {
    
    
    public int minDistance(String word1, String word2) {
    
    
        // 初始化
        int len1 = word1.length();
        int len2 = word2.length();
        // 特殊判断
        if(len1 == 0 && len2 == 0){
    
    
            return 0;
        }else if(len1 == 0 && len2 != 0){
    
    
            return len2;
        }else if(len1 != 0 && len2 == 0){
    
    
            return len1;
        }
        int[][] dp = new int[len1][len2];
        boolean flag = false; // 查重标记
        if(word1.charAt(0) == word2.charAt(0)) dp[0][0] = 0;
        else{
    
    
            dp[0][0] = 1;
            flag = true;
        };
        flag = false;
        for(int i = 1 ; i<len2 ; i++){
    
     // 由word1的第一个单词变为word2的前i+1个单词
            if(flag || word1.charAt(0) != word2.charAt(i)) dp[0][i] = dp[0][i-1]+1;
            else{
    
    
                flag = true;
                dp[0][i] = dp[0][i-1];
            }
        }
        flag = false;
        for(int i = 1 ; i<len1 ; i++){
    
     // 由word1的前i+1个单词变为word2的第一个单词
            if(flag || word1.charAt(i) != word2.charAt(0)) dp[i][0] = dp[i-1][0]+1;
            else{
    
    
                flag = true;
                dp[i][0] = dp[i-1][0];
            }
        }
        // 动态规划过程
        for(int i = 1 ; i<len1 ; i++){
    
    
            for(int j = 1 ; j<len2 ; j++){
    
    
                int temp1 = dp[i-1][j-1]+(word1.charAt(i) == word2.charAt(j)?0:1); // 替换操作
                int temp2 = dp[i][j-1]+1; // 插入操作
                int temp3 = dp[i-1][j]+1; // 删除操作
                dp[i][j] = (temp1>temp2?temp2:(temp1>temp3?temp3:temp1)); // 将最小的操作步数赋值给dp[i][j]
            }
        }
        return dp[len1-1][len2-1];
    }
}

动态规划题目,定义存储数组为dp[i][j]为word1前i+1个单词转变到word2前j+1个单词的最少操作数

考虑边界条件:
   i == 0:
   即word1的第一个单词转换为word2的前j个单词的操作数
   这里有两种情况:
   一种是word2的前j个单词包括了word1的第一个单词 dp[0][j] = j-1
   另一种是没有包括 dp[0][j] = j;
   由对称性可知:
   j == 0:
   同样有两种情况:
   一种是word2的前j个单词包括了word1的第一个单词 dp[i][0] = i-1
   另一种是没有包括 dp[i][0] = i;
其次考虑非边界条件:
   由于只有三种操作,故分三种情况讨论:
  • 替换操作:temp1 = dp[i-1][j-1] + (word1[i]==word2[j]?0:1);
  • 插入操作:temp2 = dp[i][j-1] + 1;
  • 删除操作:temp3 = dp[i-1][j] + 1;
  • 最终求:dp[i][j] = min(temp1,temp2,temp3);

猜你喜欢

转载自blog.csdn.net/weixin_43914658/article/details/113806155
今日推荐