leetcode [72. 编辑距离](https://leetcode-cn.com/problems/edit-distance/)

# leetcode [72. 编辑距离](https://leetcode-cn.com/problems/edit-distance/)

给你两个单词 `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')
```

**提示:**

- `0 <= word1.length, word2.length <= 500`
- `word1` 和 `word2` 由小写英文字母组成

Related Topics

字符串

动态规划

## 思路1:动态规划

分析:假设有单词A和B

* 删除单词A的一个字母和增加B的一个字母等价。比如A为abc,B为ab,那么在A中删除c和B中增加c编辑距离是一致的。

* 增加单词A的字母和删除B的字母等价。比如A为ab,B为abc,同上述。

* 修改单词A的字母和修改单词B的字母等价。

本质上实际的操作只有3种:

* 在单词A中插入一个字符。
* 在单词B中插入一个字符。
* 在单词A中修改一个字符。

其他操作不影响结果。比如A为abc,B为ab,我们可以执行在B中插入一个字母,也可以执行在A中删除一个字母。但是距离和最终结果都是一致的。

* 需要在单词A中插入一个字母。A为horse,B为ro,如果我们知道他们的编辑距离是a,显然,horse->ros的距离是a+1。因为horse->ro距离是a,在A后面加一个s即可。
* 需要在单词B中插入一个字母。A为hors,B为ros,如果此时的编辑距离是b,那么horse->ros的距离是b+1。A到B的编辑距离是b,那么B到A的编辑距离同样是b。ros->hors是b,那么ros->horse就是b+1.
* 需要在A中修改一个字母。如果A为hors,B为ro,编辑距离是c,那么horse->ros的距离是c+1。
* 那么horse->ros的编辑距离应该是`min(a+1,b+1,c+1) = min(a,b,c)+1` 。

最终拆分:直到某一个字符串为空:

* 当A为空,B为ros时,编辑距离刚好是ros的长度。

可以写出转移方程如下:==设`dp[i][j]`表示A中前i个字符和B中前J个字符的编辑距离==

* 如果A和B中最后一个字母相同,那么上述第三种,也就是`dp[i-1][j-1]`距离不需要加1,所以公式可以修改成`min(a,b,c-1)+1`

```java
class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();
        int[][] dp = new int[m+1][n+1];
        //计算边界
        for(int i = 1 ; i <=m;i++){
            dp[i][0] = i;
        }
        for(int j = 1; j <= n;j++){
            dp[0][j] = j;
        }
        //根据转移方程计算
        for(int i = 1; i <= m;i++){
            for(int j = 1; j <= n;j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i][j-1],dp[i-1][j-1]-1))+1;
                }else{
                    dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i][j-1],dp[i-1][j-1]))+1;
                }
            }
        }
        return dp[m][n];
    }
}
解答成功:
            执行耗时:4 ms,击败了93.15% 的Java用户
            内存消耗:41.6 MB,击败了10.40% 的Java用户
```

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值