Edit Distance
A spell checker ranks its suggestions by edit distance: the fewest single-character edits that turn the misspelled word into a dictionary word. Each edit is one of:
- inserting a character anywhere,
- deleting a character,
- replacing a character with a different one.
Given word1 and word2, return the minimum number of edits that transform word1 into word2. (This measure is also known as the Levenshtein distance.)
Input: word1 = "recieve", word2 = "receive" Output: 2
Explanation: Replace the i with e and the following e with i. The two letters are swapped, and no single edit fixes a swap.
Input: word1 = "tommorow", word2 = "tomorrow" Output: 2
Explanation: For example, delete the extra m and insert the missing r.
Input: word1 = "", word2 = "hey" Output: 3
Explanation: Starting from an empty word, every character has to be inserted.
Constraints
- Each word is between 0 and 500 characters long.
- Both words use only lowercase English letters.
Follow-up: If only insertions and deletions were allowed (no replace), how does the answer relate to the longest common subsequence?
💡 Hint 1
Work on prefixes: let dp[i][j] be the distance between the first i characters of word1 and the first j of word2. Turning a prefix into the empty string takes i deletions (and j insertions the other way).
💡 Hint 2
If the last characters match, dp[i][j] = dp[i-1][j-1]. Otherwise the last edit was a replace, a delete or an insert: 1 + min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]).
💡 Hint 3
Only the previous row is needed, so the table can be reduced to O(n) space.
Try it yourself first ✎
Solutions stick better after a real attempt. Peek when you're ready.
Approach
DP on prefixes. dp[i][j] is the edit distance between word1[0..i) and word2[0..j). The borders are dp[i][0] = i (delete everything) and dp[0][j] = j (insert everything). For the rest: if word1[i-1] === word2[j-1], no edit is needed for that pair, so dp[i][j] = dp[i-1][j-1]. Otherwise take 1 plus the cheapest of replace (dp[i-1][j-1]), delete from word1 (dp[i-1][j]) or insert into word1 (dp[i][j-1]). Each row only depends on the previous one, so two rows suffice.
function minDistance(word1, word2) {
const n = word2.length;
let prev = Array.from({ length: n + 1 }, (_, j) => j);
let curr = new Array(n + 1).fill(0);
for (let i = 1; i <= word1.length; i++) {
curr[0] = i;
for (let j = 1; j <= n; j++) {
curr[j] = word1[i - 1] === word2[j - 1] ? prev[j - 1] : 1 + Math.min(prev[j - 1], prev[j], curr[j - 1]);
}
[prev, curr] = [curr, prev];
}
return prev[n];
}class Solution {
public int minDistance(String word1, String word2) {
int n = word2.length();
int[] prev = new int[n + 1], curr = new int[n + 1];
for (int j = 0; j <= n; j++) prev[j] = j;
for (int i = 1; i <= word1.length(); i++) {
curr[0] = i;
char a = word1.charAt(i - 1);
for (int j = 1; j <= n; j++) {
curr[j] = a == word2.charAt(j - 1) ? prev[j - 1] : 1 + Math.min(prev[j - 1], Math.min(prev[j], curr[j - 1]));
}
int[] t = prev; prev = curr; curr = t;
}
return prev[n];
}
}No submissions yet. Press Submit to run your code against every test.
/**
* @param {string} word1
* @param {string} word2
* @return {number}
*/
function minDistance(word1, word2) {
}Run your code to see results here.