Leetcode【编辑距离】

72. 编辑距离

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

解题思路

  1. 定义状态:

    • 定义二维数组 dp,其中 dp[i][j] 表示将 word1 的前 i 个字符转换成 word2 的前 j 个字符所需的最小操作次数。
  2. 初始化:

    • 如果 word1 或 word2 为空,则只需将另一个字符串的所有字符插入或删除。例如:
      • dp[i][0] = i,表示将 word1 的前 i 个字符转换为空字符串的操作次数,即 i 次删除操作。
      • dp[0][j] = j,表示将空字符串转换成 word2 的前 j 个字符的操作次数,即 j 次插入操作。
  3. 状态转移:

    • 通过遍历 word1 和 word2 中的每个字符,计算 dp[i][j] 的值。对于每对字符 (i, j)
      • 插入操作:将 word1 的前 i 个字符转换成 word2 的前 j 个字符的操作次数,可以通过在 word2 中插入第 j 个字符得到,即 dp[i][j-1] + 1
      • 删除操作:将 word1 的前 i 个字符转换成 word2 的前 j 个字符的操作次数,可以通过删除 word1 中的第 i 个字符得到,即 dp[i-1][j] + 1
      • 替换操作:将 word1 的前 i 个字符转换成 word2 的前 j 个字符的操作次数,如果 word1 的第 i 个字符与 word2 的第 j 个字符不同,则需要替换,即 dp[i-1][j-1] + 1;如果相同,则不需要额外的操作,即 dp[i-1][j-1]
  4. 选择最小操作次数:

    • 对于每个 (i, j),选择插入、删除和替换操作中的最小值来更新 dp[i][j]
      dp[i][j] = Math.min(w2dowm, Math.min(w2up, update));
      
      其中 w2dowm 是删除操作的结果,w2up 是插入操作的结果,update 是替换操作的结果。
  5. 结果:

    • 最终 dp[n][m] 即为将 word1 转换为 word2 所需的最小操作次数。
public int minDistance(String word1, String word2) {
    // 获取字符串word1的长度
    int n = word1.length();
    // 获取字符串word2的长度
    int m = word2.length();
    // 如果其中一个字符串长度为0,则返回另一个字符串的长度,即为插入或删除操作的次数
    if (n * m == 0) {
        return n + m;
    }
    // 创建一个二维数组dp,dp[i][j]表示将word1的前i个字符转换成word2的前j个字符所需的最小操作次数
    int[][] dp = new int[n + 1][m + 1];
    // 初始化dp数组
    dp[0][0] = 0;
    // 初始化第一列,即将word1的前i个字符变为空字符串所需的操作次数
    for (int i = 0; i <= n; i++) {
        dp[i][0] = i;
    }
    // 初始化第一行,即将空字符串变成word2的前j个字符所需的操作次数
    for (int j = 0; j <= m; j++) {
        dp[0][j] = j;
    }
    // 遍历字符串word1的每个字符
    for (int i = 1; i <= n; i++) {
        // 遍历字符串word2的每个字符
        for (int j = 1; j <= m; j++) {
            // w2up表示插入操作,将word1的前i-1个字符转换成word2的前j个字符,再插入一个字符
            int w2up = dp[i - 1][j] + 1;
            // w2dowm表示删除操作,将word1的前i个字符转换成word2的前j-1个字符,再删除word2的第j个字符
            int w2dowm = dp[i][j - 1] + 1;
            // update表示替换操作,将word1的前i-1个字符转换成word2的前j-1个字符,如果word1的第i个字符与word2的第j个字符不同,则需要替换
            int update = dp[i - 1][j - 1];
            if (word1.charAt(i - 1) != word2.charAt(j - 1)) {
                update += 1;
            }
            // 取三种操作中的最小值作为dp[i][j]的值
            dp[i][j] = Math.min(w2dowm, Math.min(w2up, update));
        }
    }
    // 返回将word1转换成word2所需的最小操作次数,即dp[n][m]
    return dp[n][m];
}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值