Given two strings word1
and word2
, return the minimum number of steps required to make word1
and word2
the same.
In one step, you can delete exactly one character in either string.
Example 1:
Input: word1 = "sea", word2 = "eat" Output: 2 Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".
Example 2:
Input: word1 = "leetcode", word2 = "etco" Output: 4
Constraints:
1 <= word1.length, word2.length <= 500
word1
andword2
consist of only lowercase English letters.
Related Topics:
String, Dynamic Programming
Similar Questions:
- Edit Distance (Hard)
- Minimum ASCII Delete Sum for Two Strings (Medium)
- Longest Common Subsequence (Medium)
A variation of LCS problem. The result should be M + N - 2 * len(LCS)
.
// OJ: https://leetcode.com/problems/delete-operation-for-two-strings
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(MN)
class Solution {
public:
int minDistance(string s, string t) {
int M = s.size(), N = t.size();
vector<vector<int>> dp(M + 1, vector<int>(N + 1));
for (int i = 0; i < M; ++i) {
for (int j = 0; j < N; ++j) {
if (s[i] == t[j]) dp[i + 1][j + 1] = 1 + dp[i][j];
else dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]);
}
}
return M + N - 2 * dp[M][N];
}
};
Let dp[i + 1][j + 1]
be the minimum number of steps required for A[0..i]
and B[0..j]
.
for 0 <= i < M, 0 <= j < N:
dp[i+1][j+1] = dp[i][j] if s[i] == t[j]
= 1 + min(dp[i+1][j], dp[i][j+1]) if s[i] != t[j]
Trivial cases:
dp[i][0] = i for 0 <= i <= M
dp[0][j] = j for 0 <= j <= N
These trivial cases can be simplified to
dp[i][j] = i + j if i == 0 || j == 0, for 0 <= i <= M and 0 <= j <= N
// OJ: https://leetcode.com/problems/delete-operation-for-two-strings/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(MN)
class Solution {
public:
int minDistance(string s, string t) {
int M = s.size(), N = t.size();
vector<vector<int>> dp(M + 1, vector<int>(N + 1));
for (int i = 0; i <= M; ++i) dp[i][0] = i;
for (int j = 1; j <= N; ++j) dp[0][j] = j;
for (int i = 0; i < M; ++i) {
for (int j = 0; j < N; ++j) {
if (s[i] == t[j]) dp[i + 1][j + 1] = dp[i][j];
else dp[i + 1][j + 1] = 1 + min(dp[i + 1][j], dp[i][j + 1]);
}
}
return dp[M][N];
}
};
Or
// OJ: https://leetcode.com/problems/delete-operation-for-two-strings/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(MN)
class Solution {
public:
int minDistance(string A, string B) {
int M = A.size(), N = B.size();
vector<vector<int>> dp(M + 1, vector<int>(N + 1));
for (int i = 0; i <= M; ++i) {
for (int j = 0; j <= N; ++j) {
if (i == 0 || j == 0) dp[i][j] = i + j;
else if (A[i - 1] == B[j - 1]) dp[i][j] = dp[i - 1][j - 1];
else dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[M][N];
}
};
Since dp[i+1][j+1]
is only dependent on dp[i][j]
, dp[i+1][j]
and dp[i][j+1]
, we can reduce the size of the dp
array from M * N
to N
, with an additional variable saving dp[i][j]
.
// OJ: https://leetcode.com/problems/delete-operation-for-two-strings/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(min(M,N))
class Solution {
public:
int minDistance(string s, string t) {
int M = s.size(), N = t.size();
if (M < N) swap(M, N), swap(s, t);
vector<int> dp(N + 1);
for (int i = 0; i <= M; ++i) {
int prev = 0;
for (int j = 0; j <= N; ++j) {
int cur = dp[j];
if (i == 0 || j == 0) dp[j] = i + j;
else if (s[i - 1] == t[j - 1]) dp[j] = prev;
else dp[j] = 1 + min(dp[j], dp[j - 1]);
prev = cur;
}
}
return dp[N];
}
};