You are given two strings word1 and word2, each consisting of lowercase English letters.
You are allowed to perform three operations on word1 an unlimited number of times:
Return the minimum number of operations to make word1 equal word2.
Example 1:
Input: word1 = "monkeys", word2 = "money"
Output: 2Explanation:monkeys -> monkey (remove s)monkey -> money (remove k)
Example 2:
Input: word1 = "neatcdee", word2 = "neetcode"
Output: 3Explanation:neatcdee -> neetcdee (replace a with e)neetcdee -> neetcde (remove last e)neetcde -> neetcode (insert o)
Constraints:
0 <= word1.length, word2.length <= 100word1 and word2 consist of lowercase English letters.
You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m and n are the lengths of the strings word1 and word2, respectively.
Try to think in terms of recursion and visualize it as a decision tree, as we have choices at each recursion step. Can you determine the recurrence relation and base cases?
We recursively iterate through the strings using indices i and j for word1 and word2, respectively. If the characters at the current indices match, we increment both indices without counting an operation. Otherwise, we have three choices: insert the character at the current index of word1 (increment j), delete the current character of word1 (increment i), or replace the character at index i in word1 (increment both i and j).
If index i goes out of bounds, we return the number of remaining characters in word2 (using insert operations). If index j goes out of bounds, we return the number of remaining characters in word1 (using delete operations). At each step, we return the minimum operation path. This approach is exponential. Can you think of a way to optimize it?
We can use memoization to cache the results and avoid redundant calculations. A hash map or a 2D array can be used to store these results.
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
def dfs(i, j):
if i == m:
return n - j
if j == n:
return m - i
if word1[i] == word2[j]:
return dfs(i + 1, j + 1)
res = min(dfs(i + 1, j), dfs(i, j + 1))
res = min(res, dfs(i + 1, j + 1))
return res + 1
return dfs(0, 0)Where is the length of and is the length of .
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
dp = {}
def dfs(i, j):
if i == m:
return n - j
if j == n:
return m - i
if (i, j) in dp:
return dp[(i, j)]
if word1[i] == word2[j]:
dp[(i, j)] = dfs(i + 1, j + 1)
else:
res = min(dfs(i + 1, j), dfs(i, j + 1))
res = min(res, dfs(i + 1, j + 1))
dp[(i, j)] = res + 1
return dp[(i, j)]
return dfs(0, 0)Where is the length of and is the length of .
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
dp = [[float("inf")] * (len(word2) + 1) for i in range(len(word1) + 1)]
for j in range(len(word2) + 1):
dp[len(word1)][j] = len(word2) - j
for i in range(len(word1) + 1):
dp[i][len(word2)] = len(word1) - i
for i in range(len(word1) - 1, -1, -1):
for j in range(len(word2) - 1, -1, -1):
if word1[i] == word2[j]:
dp[i][j] = dp[i + 1][j + 1]
else:
dp[i][j] = 1 + min(dp[i + 1][j], dp[i][j + 1], dp[i + 1][j + 1])
return dp[0][0]Where is the length of and is the length of .
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
if m < n:
m, n = n, m
word1, word2 = word2, word1
dp = [0] * (n + 1)
nextDp = [0] * (n + 1)
for j in range(n + 1):
dp[j] = n - j
for i in range(m - 1, -1, -1):
nextDp[n] = m - i
for j in range(n - 1, -1, -1):
if word1[i] == word2[j]:
nextDp[j] = dp[j + 1]
else:
nextDp[j] = 1 + min(dp[j], nextDp[j + 1], dp[j + 1])
dp = nextDp[:]
return dp[0]Where is the length of and is the length of .
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
if m < n:
m, n = n, m
word1, word2 = word2, word1
dp = [n - i for i in range(n + 1)]
for i in range(m - 1, -1, -1):
nextDp = dp[n]
dp[n] = m - i
for j in range(n - 1, -1, -1):
temp = dp[j]
if word1[i] == word2[j]:
dp[j] = nextDp
else:
dp[j] = 1 + min(dp[j], dp[j + 1], nextDp)
nextDp = temp
return dp[0]Where is the length of and is the length of .