@@ -55,22 +55,29 @@ exection -> execution (插入 'u')
55
55
56
56
<!-- 这里可写通用的实现逻辑 -->
57
57
58
- 动态规划。
58
+ ** 方法一: 动态规划**
59
59
60
- 设 ` dp [i][j]` 表示将 word1 前 i 个字符组成的字符串 ` word1[0...i-1] ` 转换成 word2 前 j 个字符组成的字符串 ` word2[0...j-1] ` 的最小操作次数。m, n 分别表示 word1, word2 的长度 。
60
+ 我们定义 $f [ i] [ j ] $ 表示将 $ word1$ 的前 $i$ 个字符转换成 $word2$ 的前 $j$ 个字符所使用的最少操作数。初始时 $f [ i ] [ 0 ] = i$, f [ 0 ] [ j ] = j$。其中 $i \in [ 1, m ] , j \in [ 0, n ] $ 。
61
61
62
- 初始化 ` dp [i][0] = i ` ( ` i∈[0, m] ` ), ` dp[0][j] = j ` ( ` j∈[0, m] ` )。
62
+ 考虑 $f [ i] [ j ] $:
63
63
64
- i, j 分别从 1 开始遍历,判断 ` word1[i - 1] ` 与 ` word2[j - 1] ` 是否相等:
64
+ - 如果 $word1[ i - 1] = word2[ j - 1] $,那么我们只需要考虑将 $word1$ 的前 $i - 1$ 个字符转换成 $word2$ 的前 $j - 1$ 个字符所使用的最少操作数,因此 $f[ i] [ j ] = f[ i - 1] [ j - 1 ] $;
65
+ - 否则,我们可以考虑插入、删除、替换操作,那么 $f[ i] [ j ] = \min(f[ i - 1] [ j ] , f[ i] [ j - 1 ] , f[ i - 1] [ j - 1 ] ) + 1$。
65
66
66
- - 若 ` word1[i - 1] == word2[j - 1] ` ,则 ` dp[i][j] = dp[i - 1][j - 1] ` 。
67
- - 若 ` word1[i - 1] != word2[j - 1] ` ,则 ` dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 ` 。其中 ` dp[i - 1][j] + 1 ` 对应插入操作,` dp[i][j - 1] + 1 ` 对应删除操作,` dp[i - 1][j - 1] + 1 ` 对应替换操作。取三者的最小值即可。
67
+ 综上,我们可以得到状态转移方程:
68
68
69
- 递推公式如下:
69
+ $$
70
+ f[i][j] = \begin{cases}
71
+ i, & \text{if } j = 0 \\
72
+ j, & \text{if } i = 0 \\
73
+ f[i - 1][j - 1], & \text{if } word1[i - 1] = word2[j - 1] \\
74
+ \min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1, & \text{otherwise}
75
+ \end{cases}
76
+ $$
70
77
71
- ![ ] ( https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/0000-0099/0072.Edit%20Distance/images/gif.gif )
78
+ 最后,我们返回 $f [ m ] [ n ] $ 即可。
72
79
73
- 最后返回 ` dp[m][n] ` 即可 。
80
+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是 $word1$ 和 $word2$ 的长度 。
74
81
75
82
<!-- tabs:start -->
76
83
@@ -82,18 +89,17 @@ i, j 分别从 1 开始遍历,判断 `word1[i - 1]` 与 `word2[j - 1]` 是否
82
89
class Solution :
83
90
def minDistance (self , word1 : str , word2 : str ) -> int :
84
91
m, n = len (word1), len (word2)
85
- dp = [[0 ] * (n + 1 ) for _ in range (m + 1 )]
86
- for i in range (m + 1 ):
87
- dp[i][0 ] = i
88
- for j in range (n + 1 ):
89
- dp[0 ][j] = j
90
- for i in range (1 , m + 1 ):
91
- for j in range (1 , n + 1 ):
92
- if word1[i - 1 ] == word2[j - 1 ]:
93
- dp[i][j] = dp[i - 1 ][j - 1 ]
92
+ f = [[0 ] * (n + 1 ) for _ in range (m + 1 )]
93
+ for j in range (1 , n + 1 ):
94
+ f[0 ][j] = j
95
+ for i, a in enumerate (word1, 1 ):
96
+ f[i][0 ] = i
97
+ for j, b in enumerate (word2, 1 ):
98
+ if a == b:
99
+ f[i][j] = f[i - 1 ][j - 1 ]
94
100
else :
95
- dp [i][j] = min (dp[i][j - 1 ], dp[i - 1 ][j], dp [i - 1 ][j - 1 ]) + 1
96
- return dp[ - 1 ][ - 1 ]
101
+ f [i][j] = min (f[i - 1 ][j], f[i][j - 1 ], f [i - 1 ][j - 1 ]) + 1
102
+ return f[m][n ]
97
103
```
98
104
99
105
### ** Java**
@@ -104,23 +110,21 @@ class Solution:
104
110
class Solution {
105
111
public int minDistance (String word1 , String word2 ) {
106
112
int m = word1. length(), n = word2. length();
107
- int [][] dp = new int [m + 1 ][n + 1 ];
108
- for (int i = 0 ; i <= m; ++ i) {
109
- dp[i][0 ] = i;
110
- }
111
- for (int j = 0 ; j <= n; ++ j) {
112
- dp[0 ][j] = j;
113
+ int [][] f = new int [m + 1 ][n + 1 ];
114
+ for (int j = 1 ; j <= n; ++ j) {
115
+ f[0 ][j] = j;
113
116
}
114
117
for (int i = 1 ; i <= m; ++ i) {
118
+ f[i][0 ] = i;
115
119
for (int j = 1 ; j <= n; ++ j) {
116
120
if (word1. charAt(i - 1 ) == word2. charAt(j - 1 )) {
117
- dp [i][j] = dp [i - 1 ][j - 1 ];
121
+ f [i][j] = f [i - 1 ][j - 1 ];
118
122
} else {
119
- dp [i][j] = Math . min(Math . min(dp[i][j - 1 ], dp[i - 1 ][j]), dp [i - 1 ][j - 1 ]) + 1 ;
123
+ f [i][j] = Math . min(f[i - 1 ][j], Math . min(f[i][j - 1 ], f [i - 1 ][j - 1 ]) ) + 1 ;
120
124
}
121
125
}
122
126
}
123
- return dp [m][n];
127
+ return f [m][n];
124
128
}
125
129
}
126
130
```
@@ -132,23 +136,21 @@ class Solution {
132
136
public:
133
137
int minDistance(string word1, string word2) {
134
138
int m = word1.size(), n = word2.size();
135
- vector<vector<int >> dp(m + 1, vector<int >(n + 1));
136
- for (int i = 0; i <= m; ++i) {
137
- dp[ i] [ 0 ] = i;
138
- }
139
+ int f[ m + 1] [ n + 1 ] ;
139
140
for (int j = 0; j <= n; ++j) {
140
- dp [ 0] [ j ] = j;
141
+ f [ 0] [ j ] = j;
141
142
}
142
143
for (int i = 1; i <= m; ++i) {
144
+ f[ i] [ 0 ] = i;
143
145
for (int j = 1; j <= n; ++j) {
144
146
if (word1[ i - 1] == word2[ j - 1] ) {
145
- dp [ i] [ j ] = dp [ i - 1] [ j - 1 ] ;
147
+ f [ i] [ j ] = f [ i - 1] [ j - 1 ] ;
146
148
} else {
147
- dp [ i] [ j ] = min(min(dp [ i - 1] [ j ] , dp [ i] [ j - 1 ] ), dp [ i - 1] [ j - 1 ] ) + 1;
149
+ f [ i] [ j ] = min({f [ i - 1] [ j ] , f [ i] [ j - 1 ] , f [ i - 1] [ j - 1 ] } ) + 1;
148
150
}
149
151
}
150
152
}
151
- return dp [ m] [ n ] ;
153
+ return f [ m] [ n ] ;
152
154
}
153
155
};
154
156
```
@@ -158,24 +160,24 @@ public:
158
160
```go
159
161
func minDistance(word1 string, word2 string) int {
160
162
m, n := len(word1), len(word2)
161
- dp := make([][]int, m+1)
162
- for i := 0; i <= m; i++ {
163
- dp[i] = make([]int, n+1)
164
- dp[i][0] = i
163
+ f := make([][]int, m+1)
164
+ for i := range f {
165
+ f[i] = make([]int, n+1)
165
166
}
166
- for j := 0 ; j <= n; j++ {
167
- dp [0][j] = j
167
+ for j := 1 ; j <= n; j++ {
168
+ f [0][j] = j
168
169
}
169
170
for i := 1; i <= m; i++ {
171
+ f[i][0] = i
170
172
for j := 1; j <= n; j++ {
171
173
if word1[i-1] == word2[j-1] {
172
- dp [i][j] = dp [i-1][j-1]
174
+ f [i][j] = f [i-1][j-1]
173
175
} else {
174
- dp [i][j] = min(min(dp [i-1][j], dp [i][j-1]), dp [i-1][j-1]) + 1
176
+ f [i][j] = min(f [i-1][j], min(f [i][j-1], f [i-1][j-1]) ) + 1
175
177
}
176
178
}
177
179
}
178
- return dp [m][n]
180
+ return f [m][n]
179
181
}
180
182
181
183
func min(a, b int) int {
@@ -186,6 +188,33 @@ func min(a, b int) int {
186
188
}
187
189
```
188
190
191
+ ### ** TypeScript**
192
+
193
+ ``` ts
194
+ function minDistance(word1 : string , word2 : string ): number {
195
+ const m = word1 .length ;
196
+ const n = word2 .length ;
197
+ const f: number [][] = Array (m + 1 )
198
+ .fill (0 )
199
+ .map (() => Array (n + 1 ).fill (0 ));
200
+ for (let j = 1 ; j <= n ; ++ j ) {
201
+ f [0 ][j ] = j ;
202
+ }
203
+ for (let i = 1 ; i <= m ; ++ i ) {
204
+ f [i ][0 ] = i ;
205
+ for (let j = 1 ; j <= n ; ++ j ) {
206
+ if (word1 [i - 1 ] === word2 [j - 1 ]) {
207
+ f [i ][j ] = f [i - 1 ][j - 1 ];
208
+ } else {
209
+ f [i ][j ] =
210
+ Math .min (f [i - 1 ][j ], f [i ][j - 1 ], f [i - 1 ][j - 1 ]) + 1 ;
211
+ }
212
+ }
213
+ }
214
+ return f [m ][n ];
215
+ }
216
+ ```
217
+
189
218
### ** ...**
190
219
191
220
```
0 commit comments