Edit Distance

MediumString DP · 2-D Table🧩 String DPLeetCode #72 ↗Updated

Problem

You are given two strings word1 and word2. In one step you may insert a character, delete a character or replace a character of word1. Return the fewest steps needed to turn word1 into word2.
Inputword1 = "horse", word2 = "ros"Output3 (h→r, drop r, drop e)
Inputword1 = "intention", word2 = "execution"Output5
Inputword1 = "", word2 = "abc"Output3

0 ≤ word1.length, word2.length ≤ 500  ·  lowercase English letters only

Try it yourself

Java
class Solution {
    public int minDistance(String word1, String word2) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Only the last characters matter at each step: if they match, drop both for free; otherwise pay 1 for replace, delete or insert and recurse on a shorter prefix pair. There are just (m+1)×(n+1) prefix pairs, so a table kills the exponential blow-up.
PatternString DP

Instinct Two strings compared char by char (match, edit, interleave) means dp[i][j] over prefixes; one string's palindromes or splits means dp[l][r] or dp[i].

Memory hack Match? Go diagonal. Mismatch? Ask the neighbours. Up drops a char from s, left drops one from t, diagonal uses both.

Open the String DP guide →

Approaches

Brute ForcePlain Recursion on Prefixes

Time O(3m+n)Space O(m+n)

Let solve(i, j) be the cost to turn the first i chars of word1 into the first j chars of word2. If one prefix is empty the answer is the other's length. Equal last chars cost nothing; otherwise try all three edits and keep the cheapest.

Java
public int minDistance(String word1, String word2) {
    return solve(word1, word2, word1.length(), word2.length());
}

private int solve(String a, String b, int i, int j) {
    if (i == 0) return j; // insert the rest of b
    if (j == 0) return i; // delete the rest of a
    if (a.charAt(i - 1) == b.charAt(j - 1)) return solve(a, b, i - 1, j - 1);
    int replace = solve(a, b, i - 1, j - 1);
    int delete = solve(a, b, i - 1, j);
    int insert = solve(a, b, i, j - 1);
    return 1 + Math.min(replace, Math.min(delete, insert));
}

Correct and shows the recurrence, but recomputes the same prefix pairs endlessly.

At a glance

LevelApproachTimeSpace
Brute ForcePlain Recursion on PrefixesO(3m+n)O(m+n)
BetterBottom-Up 2-D TableO(m·n)O(m·n)
OptimalSingle Rolling RowO(m·n)O(n)
Common pitfalls
  • Mixing up which neighbour means insert vs delete — both cost 1, but name them right.
  • Forgetting the base row/column — turning a prefix into "" costs its length.
  • In the 1-D version, reading dp[j] after overwriting it — save up first.
Interview tips
  • Define the state out loud: cost to convert word1[0..i) into word2[0..j).
  • Draw the 3 arrows (diag, up, left) and map each to an operation.
  • Mention the row-rolling trick unprompted — it is the usual follow-up.
Pattern
Two-string prefix DP → when the answer for two strings depends only on shorter prefixes of both.
My notes saved in this browser