Skip to content

Commit 4874513

Browse files
committed
add for code
1 parent f9db37c commit 4874513

6 files changed

+245
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com..houbb.leetcode.topics.editdistance;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class T72_minDistanceList_V1_DP {
7+
8+
public static void main(String[] args) {
9+
T72_minDistanceList_V1_DP dp = new T72_minDistanceList_V1_DP();
10+
System.out.println(dp.minDistance("horse", "ros"));
11+
}
12+
13+
14+
public List<String> minDistance(String word1, String word2) {
15+
int m = word1.length();
16+
int n = word2.length();
17+
18+
// DP数组,记录最小操作数
19+
int[][] dp = new int[m + 1][n + 1];
20+
// 操作类型数组,记录操作类型:"" = no-op, "insert", "delete", "replace"
21+
String[][] operation = new String[m + 1][n + 1];
22+
23+
// 初始化
24+
for (int i = 0; i <= m; i++) {
25+
dp[i][0] = i;
26+
operation[i][0] = "delete";
27+
}
28+
for (int j = 0; j <= n; j++) {
29+
dp[0][j] = j;
30+
operation[0][j] = "insert";
31+
}
32+
33+
// 填充DP表和操作类型表
34+
for (int i = 1; i <= m; i++) {
35+
for (int j = 1; j <= n; j++) {
36+
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
37+
dp[i][j] = dp[i - 1][j - 1];
38+
operation[i][j] = ""; // 字符相等,不需要操作
39+
} else {
40+
int insert = dp[i][j - 1] + 1;
41+
int delete = dp[i - 1][j] + 1;
42+
int replace = dp[i - 1][j - 1] + 1;
43+
44+
// 选择最小的操作
45+
dp[i][j] = Math.min(Math.min(insert, delete), replace);
46+
47+
// 记录操作类型
48+
if (dp[i][j] == insert) {
49+
operation[i][j] = "insert";
50+
} else if (dp[i][j] == delete) {
51+
operation[i][j] = "delete";
52+
} else {
53+
operation[i][j] = "replace";
54+
}
55+
}
56+
}
57+
}
58+
59+
// 回溯操作路径,生成变换过程
60+
List<String> result = new ArrayList<>();
61+
int i = m, j = n;
62+
StringBuilder currentWord = new StringBuilder(word1);
63+
64+
// 回溯路径
65+
while (i > 0 || j > 0) {
66+
addNewWord(result, currentWord.toString());
67+
if (operation[i][j].equals("")) {
68+
i--;
69+
j--;
70+
} else if (operation[i][j].equals("insert")) {
71+
currentWord.insert(i, word2.charAt(j - 1));
72+
j--;
73+
} else if (operation[i][j].equals("delete")) {
74+
currentWord.deleteCharAt(i - 1);
75+
i--;
76+
} else if (operation[i][j].equals("replace")) {
77+
currentWord.setCharAt(i - 1, word2.charAt(j - 1));
78+
i--;
79+
j--;
80+
}
81+
}
82+
83+
// 添加初始单词到变换过程
84+
addNewWord(result, currentWord.toString());
85+
86+
// 由于回溯是从后往前的,因此需要反转结果
87+
// Collections.reverse(result);
88+
return result;
89+
}
90+
91+
// 避免数据重复
92+
private void addNewWord(List<String> list, String word) {
93+
if(list.size() > 0 && word.equals(list.get(list.size()-1))) {
94+
return;
95+
}
96+
97+
list.add(word);
98+
}
99+
100+
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com..houbb.leetcode.topics.editdistance;
2+
3+
public class T72_minDistance_V1_BF {
4+
5+
public int minDistance(String word1, String word2) {
6+
return helper(word1, word2, word1.length(), word2.length());
7+
}
8+
9+
// 递归函数,计算word1[0..i]到word2[0..j]的最小编辑距离
10+
private int helper(String word1, String word2, int i, int j) {
11+
// 如果 word1 为空,则需要插入所有 word2 的字符
12+
if (i == 0) return j;
13+
14+
// 如果 word2 为空,则需要删除所有 word1 的字符
15+
if (j == 0) return i;
16+
17+
// 如果字符相等,则不需要任何操作,直接比较剩下的子串
18+
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
19+
return helper(word1, word2, i - 1, j - 1);
20+
}
21+
22+
// 如果字符不相等,则考虑三种操作
23+
int insert = helper(word1, word2, i, j - 1); // 插入
24+
int delete = helper(word1, word2, i - 1, j); // 删除
25+
int replace = helper(word1, word2, i - 1, j - 1); // 替换
26+
27+
// 返回三种操作中的最小值 + 1(表示进行了一次操作)
28+
return 1 + Math.min(Math.min(insert, delete), replace);
29+
}
30+
31+
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com..houbb.leetcode.topics.editdistance;
2+
3+
public class T72_minDistance_V2_BF_memory {
4+
5+
public int minDistance(String word1, String word2) {
6+
int m = word1.length();
7+
int n = word2.length();
8+
Integer[][] memo = new Integer[m + 1][n + 1];
9+
return helper(word1, word2, m, n, memo);
10+
}
11+
12+
private int helper(String word1, String word2, int i, int j, Integer[][] memo) {
13+
// 递归终止条件
14+
if (i == 0) return j; // 将空字符串转换成 word2[0..j-1]
15+
if (j == 0) return i; // 将 word1[0..i-1] 转换成空字符串
16+
17+
// 如果已经计算过该子问题,直接返回结果
18+
if (memo[i][j] != null) return memo[i][j];
19+
20+
// 计算当前子问题的解
21+
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
22+
memo[i][j] = helper(word1, word2, i - 1, j - 1, memo); // 字符相等,不需要任何操作
23+
} else {
24+
// 否则,考虑三种操作
25+
int insert = helper(word1, word2, i, j - 1, memo); // 插入
26+
int delete = helper(word1, word2, i - 1, j, memo); // 删除
27+
int replace = helper(word1, word2, i - 1, j - 1, memo); // 替换
28+
memo[i][j] = Math.min(Math.min(insert, delete), replace) + 1;
29+
}
30+
31+
return memo[i][j];
32+
}
33+
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com..houbb.leetcode.topics.editdistance;
2+
3+
public class T72_minDistance_V3_DP {
4+
5+
public int minDistance(String word1, String word2) {
6+
int m = word1.length();
7+
int n = word2.length();
8+
9+
// 创建dp数组,dp[i][j]表示word1[0..i-1]转换为word2[0..j-1]的最小操作数
10+
int[][] dp = new int[m + 1][n + 1];
11+
12+
// 初始化第一列和第一行
13+
for (int i = 0; i <= m; i++) {
14+
dp[i][0] = i; // 从word1[0..i-1]变为空字符串需要i次删除
15+
}
16+
17+
for (int j = 0; j <= n; j++) {
18+
dp[0][j] = j; // 从空字符串变成word2[0..j-1]需要j次插入
19+
}
20+
21+
// 填充dp表
22+
for (int i = 1; i <= m; i++) {
23+
for (int j = 1; j <= n; j++) {
24+
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
25+
dp[i][j] = dp[i - 1][j - 1]; // 如果字符相等,不需要任何操作
26+
} else {
27+
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
28+
// 三种操作:删除、插入、替换
29+
}
30+
}
31+
}
32+
33+
// 最终结果是将word1完全转为word2
34+
return dp[m][n];
35+
}
36+
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com..houbb.leetcode.topics.editdistance;
2+
3+
public class T72_minDistance_V4_DP_memOpt {
4+
5+
public int minDistance(String word1, String word2) {
6+
int m = word1.length();
7+
int n = word2.length();
8+
9+
// 用两个一维数组代替二维数组
10+
int[] prev = new int[n + 1];
11+
int[] curr = new int[n + 1];
12+
13+
// 初始化第一行
14+
for (int j = 0; j <= n; j++) {
15+
prev[j] = j;
16+
}
17+
18+
// 填充动态规划表
19+
for (int i = 1; i <= m; i++) {
20+
curr[0] = i; // 第i行的第0列,表示将word1[0..i-1]转换为空字符串,需要i次删除
21+
for (int j = 1; j <= n; j++) {
22+
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
23+
curr[j] = prev[j - 1]; // 字符相等,无需操作
24+
} else {
25+
curr[j] = Math.min(Math.min(prev[j], curr[j - 1]), prev[j - 1]) + 1; // 三种操作的最小值
26+
}
27+
}
28+
// 更新prev和curr
29+
int[] temp = prev;
30+
prev = curr;
31+
curr = temp;
32+
}
33+
34+
return prev[n]; // 返回最后的结果
35+
}
36+
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package com..houbb.leetcode.topics;

0 commit comments

Comments
 (0)