# 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用户
```