| Difficulty | Hard | ||
|---|---|---|---|
| Source | 160 Days of Problem Solving | ||
| Tags |
|
The problem can be found at the following link: Question Link
Given two strings s1 and s2, you need to find the minimum number of operations required to convert s1 into s2. The valid operations are:
- Insert a character at any position.
- Delete any character from the string.
- Replace any character with another character.
s1 = "geek"
s2 = "gesek"
1
We can insert 's' between the two 'e' in "geek" to form "gesek".
s1 = "gfg"
s2 = "gfg"
0
The strings are already the same, so 0 operations are required.
s1 = "abcd"
s2 = "bcfe"
3
- Remove
'a'from "abcd" → "bcd" - Replace
'd'with'f'→ "bcf" - Insert
'e'at the end → "bcfe"
$(1 \leq s1.length(), s2.length() \leq 10^3)$ - Both strings are in lowercase.
- We use two 1D arrays (
prevandcurr) of size ( n+1 ) (where ( n ) is the length of ( s2 )). - Initialize the
prevarray such thatprev[j] = j, meaning if ( s1 ) is empty, it takesjoperations (all inserts) to match ( s2[0..j-1] ). - Iterate over each character in ( s1 ) (index
i) and fillcurr:curr[0] = i(if ( s2 ) is empty, we needideletions to match).- For each
jin ( s2 ), compares1[i-1]withs2[j-1]:- If they match, carry over
prev[j-1]. - Otherwise,
curr[j] = 1 + min({ replace, delete, insert }).
- If they match, carry over
- Swap
prevandcurrafter each iteration to save space. - Finally,
prev[n]holds the edit distance.
- Let
$( m = \text{length}(s1), n = \text{length}(s2) )$ . - Initialize
prevarray of size ( n+1 ) withprev[j] = j. - Loop
ifrom1tom:- Set
curr[0] = i. - For each
jfrom1ton:- If
s1[i-1] == s2[j-1], thencurr[j] = prev[j-1]. - Else
curr[j] = 1 + min( prev[j-1], prev[j], curr[j-1] ).
- If
- Swap
prevandcurr.
- Set
- Answer is
prev[n].
-
Expected Time Complexity:
$( O(M \times N) )$ , as we iterate through each character of$( s1 )$ and$( s2 )$ . -
Expected Auxiliary Space Complexity:
$( O(N) )$ , because we only keep two 1D arrays of size$( n+1 )$ .
class Solution {
public:
int editDistance(string& s1, string& s2) {
int m = s1.size(), n = s2.size();
vector<int> prev(n + 1), curr(n + 1);
iota(prev.begin(), prev.end(), 0);
for (int i = 1; i <= m; i++) {
curr[0] = i;
for (int j = 1; j <= n; j++)
curr[j] = s1[i-1] == s2[j-1] ? prev[j-1] : 1 + min({prev[j-1], prev[j], curr[j-1]});
swap(prev, curr);
}
return prev[n];
}
};Idea:
- Create a 2D DP array where
dp[i][j]represents the minimum operations to converts1[0...i-1]tos2[0...j-1]. - If characters match, carry forward the diagonal value.
- Otherwise, consider the minimum of insert, delete, and replace.
class Solution {
public:
int editDistance(string& s1, string& s2) {
int m = s1.size(), n = s2.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 = 0; j <= n; j++) dp[0][j] = j;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1];
else dp[i][j] = 1 + min({dp[i-1][j-1], dp[i-1][j], dp[i][j-1]});
}
}
return dp[m][n];
}
};🔹 More intuitive for understanding
🔹 Easier to debug
| Approach | ⏱️ Time Complexity | 🗂️ Space Complexity | ✅ Pros | |
|---|---|---|---|---|
| Space Optimized DP (1D) | 🟡 O(M * N) | 🟢 O(N) | Efficient for large data | Slightly harder to debug |
| DP (2D Table) | 🟡 O(M * N) | 🟡 O(M * N) | Easier to understand | More memory-intensive |
- ✅ For learning concepts: Use the 2D DP approach.
- ✅ For optimal performance: Use the Space Optimized DP approach.
class Solution {
public int editDistance(String s1, String s2) {
int m = s1.length(), n = s2.length();
int[] prev = new int[n + 1], curr = new int[n + 1];
for (int i = 0; i <= n; i++) prev[i] = i;
for (int i = 1; i <= m; i++) {
curr[0] = i;
for (int j = 1; j <= n; j++)
curr[j] = s1.charAt(i-1) == s2.charAt(j-1) ? prev[j-1] : 1 + Math.min(prev[j-1], Math.min(prev[j], curr[j-1]));
int[] temp = prev;
prev = curr;
curr = temp;
}
return prev[n];
}
}class Solution:
def editDistance(self, s1, s2):
m, n = len(s1), len(s2)
prev, curr = list(range(n + 1)), [0] * (n + 1)
for i in range(1, m + 1):
curr[0] = i
for j in range(1, n + 1):
curr[j] = prev[j-1] if s1[i-1] == s2[j-1] else 1 + min(prev[j-1], prev[j], curr[j-1])
prev, curr = curr, prev
return prev[n]For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Let’s make this learning journey more collaborative!
⭐ If you find this helpful, please give this repository a star! ⭐