Leetcode72. 编辑距离Edit Distance(Java)
动态规划
对字符操作的顺序并不能影响结果
因此,将字符串操作顺序规定为从左到右操作
f
(
i
,
j
)
f(i,j)
f(i,j)表示将长度为i
的字符串A
修改成为长度为j
的字符串B
的操作所需的最小操作数
则只可能分以下6种情况
-
字符串
A
末尾删除一个字符后与字符串B
相同
f ( i , j ) = f ( i − 1 , j ) + 1 f(i,j) = f(i - 1, j) + 1 f(i,j)=f(i−1,j)+1
表示字符串A
的前i-1
项与字符串的前j
项相同,只需进行一次删除操作就可以实现使字符串相同 -
字符串
A
末尾增加一个字符后与字符串B
相同
f ( i , j ) = f ( i , j − 1 ) + 1 f(i,j) = f(i, j - 1) + 1 f(i,j)=f(i,j−1)+1
表示字符串A
的前i
项与字符串的前j-1
项相同,只需进行一次增加操作就可以实现使字符串相同,增加字符为字符串B
的第j
个字符 -
字符串
B
末尾删除一个字符后与字符串A
相同f ( i , j ) = f ( i , j − 1 ) + 1 f(i,j) = f(i, j - 1) + 1 f(i,j)=f(i,j−1)+1,同理可得
-
字符串
B
末尾增加一个字符后与字符串A
相同f ( i , j ) = f ( i − 1 , j ) + 1 f(i,j) = f(i - 1, j) + 1 f(i,j)=f(i−1,j)+1,同理可得
-
字符串
A
末尾元素修改一个,与字符串B
相同(修改A
末尾与修改B
末尾操作本质相同)f ( i , j ) = f ( i − 1 , j − 1 ) + 1 f(i,j) = f(i-1,j-1) + 1 f(i,j)=f(i−1,j−1)+1
-
字符串
A
末尾元素与字符串B
末尾元素相同f ( i , j ) = f ( i − 1 , j − 1 ) f(i,j) = f(i-1,j-1) f(i,j)=f(i−1,j−1)
由上分析实际情况分四种
-
A
末尾删除或B
末尾增加f ( i , j ) = f ( i − 1 , j ) + 1 f(i,j) = f(i - 1, j) + 1 f(i,j)=f(i−1,j)+1
-
A
末尾增加B
末尾删除f ( i , j ) = f ( i , j − 1 ) + 1 f(i,j) = f(i, j - 1) + 1 f(i,j)=f(i,j−1)+1
-
A
或B
末尾元素修改一个f ( i , j ) = f ( i − 1 , j − 1 ) + 1 f(i,j) = f(i-1,j-1) + 1 f(i,j)=f(i−1,j−1)+1
-
字符串
A
末尾元素与字符串B
末尾元素相同f ( i , j ) = f ( i − 1 , j − 1 ) f(i,j) = f(i-1,j-1) f(i,j)=f(i−1,j−1)
初始化
对于
f
(
i
,
0
)
f(i,0)
f(i,0)和
f
(
0
,
i
)
f(0,i)
f(0,i)所代表的实际含义是将以长度为0
的字符串变为长度为i
的字符串,因此操作步数应该为增加i
个元素
时间复杂度: O ( n m ) O(nm) O(nm)
class Solution {
public int minDistance(String word1, String word2) {
int n = word1.length(), m = word2.length();
int[][] dp = new int[n + 10][m + 10];
for (int i = 0; i <= n; i ++) dp[i][0] = i;
for (int j = 0; j <= m; j ++) dp[0][j] = j;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]),dp[i - 1][j - 1]) + 1;
}
}
}
return dp[n][m];
}
}