Skip to content

Commit af133eb

Browse files
committed
0072-edit-distance.md Added 7 languages solutions.
1 parent ba530e2 commit af133eb

File tree

2 files changed

+263
-0
lines changed

2 files changed

+263
-0
lines changed

0072-edit-distance.md

+262
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
# 72. Edit Distance
2+
LeetCode problem: [72. Edit Distance](https://leetcode.com/problems/edit-distance/)
3+
4+
## LeetCode problem description
5+
> Given two strings `word1` and `word2`, return the **minimum** number of operations required to convert `word1` to `word2`.
6+
7+
You have the following three operations permitted on a word:
8+
- Insert a character
9+
- Delete a character
10+
- Replace a character
11+
12+
```
13+
Example 1:
14+
Input: word1 = "horse", word2 = "ros"
15+
Output: 3
16+
Explanation:
17+
horse -> rorse (replace 'h' with 'r')
18+
rorse -> rose (remove 'r')
19+
rose -> ros (remove 'e')
20+
-----------------------------------------------
21+
Example 2:
22+
Input: word1 = "intention", word2 = "execution"
23+
Output: 5
24+
Explanation:
25+
intention -> inention (remove 't')
26+
inention -> enention (replace 'i' with 'e')
27+
enention -> exention (replace 'n' with 'x')
28+
exention -> exection (replace 'n' with 'c')
29+
exection -> execution (insert 'u')
30+
```
31+
32+
## Thoughts
33+
* It is a question of comparing two strings. After doing similar questions many times, we will develop an intuition to use dynamic programming with two-dimensional arrays.
34+
35+
### Common steps in dynamic programming
36+
These five steps are a pattern for solving dynamic programming problems.
37+
38+
1. Determine the **meaning** of the `dp[i][j]`
39+
* Since there are two strings, we can use two-dimensional arrays as the default option.
40+
* At first, try to use the problem's `return` value as the value of `dp[i][j]` to determine the meaning of `dp[i][j]`. If it doesn't work, try another way.
41+
* `dp[i][j]` represents the **minimum** number of operations required to convert `word1`'s first `i` letters to `word2`'s first `j` letters.
42+
* The value of `dp[i][j]` is an integer.
43+
2. Determine the `dp` array's initial value
44+
* Use an example:
45+
```
46+
After initialized, the 'dp' array would be:
47+
# r o s
48+
# 0 1 2 3 # dp[0]
49+
# h 1 0 0 0
50+
# o 2 0 0 0
51+
# r 3 0 0 0
52+
# s 4 0 0 0
53+
# e 5 0 0 0
54+
```
55+
* `dp[i][0] = i`, because `dp[i][0]` represents the empty string, and the number of operations is just the number of chars to be deleted.
56+
* `dp[0][j] = j`, the reason is the same as the previous line, just viewed from the opposite angle: convert `word2` to `word1`.
57+
58+
3. Determine the `dp` array's recurrence formula
59+
```
60+
The final 'dp' array would be:
61+
# r o s
62+
# 0 1 2 3 # dp[0]
63+
# h 1 1 2 3
64+
# o 2 2 1 2
65+
# r 3 2 2 2
66+
# s 4 3 3 2
67+
# e 5 4 4 3
68+
```
69+
* When analyzing the sample `dp` grid, remember there are three important points which you should pay special attention to: `dp[i - 1][j - 1]`, `dp[i - 1][j]` and `dp[i][j - 1]`. The current `dp[i][j]` often depends on them.
70+
* If we need to use `dp[i - 1][j]` or `dp[i][j - 1]`, and the question is also true in reverse, then we probably need to use both of them.
71+
* We can derive the `Recurrence Formula`:
72+
```python
73+
if word1[i - 1] == word2[j - 1]
74+
dp[i][j] = dp[i - 1][j - 1]
75+
else
76+
dp[i][j] = min(
77+
dp[i - 1][j - 1],
78+
dp[i - 1][j],
79+
dp[i][j - 1],
80+
) + 1
81+
```
82+
4. Determine the `dp` array's traversal order
83+
* `dp[i][j]` depends on `dp[i - 1][j - 1]`, `dp[i - 1][j]` and `dp[i][j - 1]`, so we should traverse the `dp` array from top to bottom, then from left to right.
84+
5. Check the `dp` array's value
85+
* Print the `dp` to see if it is as expected.
86+
87+
### Complexity
88+
* Time: `O(n * m)`.
89+
* Space: `O(n * m)`.
90+
91+
## Python
92+
```python
93+
class Solution:
94+
def minDistance(self, word1: str, word2: str) -> int:
95+
dp = [[0] * (len(word2) + 1) for _ in range(len(word1) + 1)]
96+
for i in range(len(dp)):
97+
dp[i][0] = i
98+
for j in range(len(dp[0])):
99+
dp[0][j] = j
100+
101+
for i in range(1, len(dp)):
102+
for j in range(1, len(dp[0])):
103+
if word1[i - 1] == word2[j - 1]:
104+
dp[i][j] = dp[i - 1][j - 1]
105+
else:
106+
dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1
107+
108+
return dp[-1][-1]
109+
```
110+
111+
## C++
112+
```cpp
113+
class Solution {
114+
public:
115+
int minDistance(string word1, string word2) {
116+
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
117+
for (int i = 0; i < dp.size(); i++)
118+
dp[i][0] = i;
119+
for (int j = 0; j < dp[0].size(); j++)
120+
dp[0][j] = j;
121+
122+
for (int i = 1; i < dp.size(); i++) {
123+
for (int j = 1; j < dp[0].size(); j++) {
124+
if (word1[i - 1] == word2[j - 1])
125+
dp[i][j] = dp[i - 1][j - 1];
126+
else
127+
dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
128+
}
129+
}
130+
131+
return dp[dp.size() - 1][dp[0].size() - 1];
132+
}
133+
};
134+
```
135+
136+
## Java
137+
```java
138+
class Solution {
139+
public int minDistance(String word1, String word2) {
140+
var dp = new int[word1.length() + 1][word2.length() + 1];
141+
for (int i = 0; i < dp.length; i++)
142+
dp[i][0] = i;
143+
for (int j = 0; j < dp[0].length; j++)
144+
dp[0][j] = j;
145+
146+
for (int i = 1; i < dp.length; i++) {
147+
for (int j = 1; j < dp[0].length; j++) {
148+
if (word1.charAt(i - 1) == word2.charAt(j - 1))
149+
dp[i][j] = dp[i - 1][j - 1];
150+
else
151+
dp[i][j] = Math.min(
152+
dp[i - 1][j - 1],
153+
Math.min(dp[i - 1][j], dp[i][j - 1])
154+
) + 1;
155+
}
156+
}
157+
158+
return dp[dp.length - 1][dp[0].length - 1];
159+
}
160+
}
161+
```
162+
163+
## C#
164+
```c#
165+
public class Solution {
166+
public int MinDistance(string word1, string word2) {
167+
var dp = new int[word1.Length + 1][];
168+
for (int i = 0; i < dp.Length; i++) {
169+
dp[i] = new int[word2.Length + 1];
170+
dp[i][0] = i;
171+
}
172+
for (int j = 0; j < dp[0].Length; j++)
173+
dp[0][j] = j;
174+
175+
for (int i = 1; i < dp.Length; i++) {
176+
for (int j = 1; j < dp[0].Length; j++) {
177+
if (word1[i - 1] == word2[j - 1])
178+
dp[i][j] = dp[i - 1][j - 1];
179+
else
180+
dp[i][j] = Math.Min(
181+
dp[i - 1][j - 1],
182+
Math.Min(dp[i - 1][j], dp[i][j - 1])
183+
) + 1;
184+
}
185+
}
186+
187+
return dp[dp.Length - 1][dp[0].Length - 1];
188+
}
189+
}
190+
```
191+
192+
## JavaScript
193+
```javascript
194+
var minDistance = function(word1, word2) {
195+
let dp = Array(word1.length + 1).fill().map(
196+
() => Array(word2.length + 1).fill(0)
197+
)
198+
dp.forEach((_, i) => { dp[i][0] = i })
199+
dp[0].forEach((_, j) => { dp[0][j] = j })
200+
201+
for (let i = 1; i < dp.length; i++) {
202+
for (let j = 1; j < dp[0].length; j++) {
203+
if (word1[i - 1] == word2[j - 1])
204+
dp[i][j] = dp[i - 1][j - 1]
205+
else
206+
dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1
207+
}
208+
}
209+
210+
return dp.at(-1).at(-1)
211+
};
212+
```
213+
214+
## Go
215+
```go
216+
func minDistance(word1 string, word2 string) int {
217+
dp := make([][]int, len(word1) + 1)
218+
for i := range dp {
219+
dp[i] = make([]int, len(word2) + 1)
220+
dp[i][0] = i
221+
}
222+
for j := range dp[0] {
223+
dp[0][j] = j
224+
}
225+
226+
for i := 1; i < len(dp); i++ {
227+
for j := 1; j < len(dp[0]); j++ {
228+
if word1[i - 1] == word2[j - 1] {
229+
dp[i][j] = dp[i - 1][j - 1]
230+
} else {
231+
dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1
232+
}
233+
}
234+
}
235+
236+
return dp[len(dp) - 1][len(dp[0]) - 1]
237+
}
238+
```
239+
240+
## Ruby
241+
```ruby
242+
def min_distance(word1, word2)
243+
dp = Array.new(word1.size + 1) do |i|
244+
Array.new(word2.size + 1, 0)
245+
end
246+
dp.each_with_index { |_, i| dp[i][0] = i }
247+
dp[0].each_with_index { |_, j| dp[0][j] = j }
248+
249+
for i in 1..dp.size - 1
250+
for j in 1..dp[0].size - 1
251+
dp[i][j] =
252+
if word1[i - 1] == word2[j - 1]
253+
dp[i - 1][j - 1]
254+
else
255+
[dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]].min + 1
256+
end
257+
end
258+
end
259+
260+
dp[-1][-1]
261+
end
262+
```

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
- [53. Maximum Subarray](./0053-maximum-subarray.md)
33
- [392. Is Subsequence](./0392-is-subsequence.md)
44
- [583. Delete Operation for Two Strings](./0583-delete-operation-for-two-strings.md)
5+
- [72. Edit Distance](./0072-edit-distance.md)
56

67
- More LeetCode problems will be added soon...

0 commit comments

Comments
 (0)