2Brute2Best
🔥0

Edit Distance

Medium·LeetCode #72Basic Anchor
LeetCode
30-Second Mental ModelDP — Strings, Edit distance (minimum of insert, delete, replace)
Complexity:O(3^(N + M))→O(N · M)
Key Insight

A cell reads the row above it and the cell to its left. So keep two rows: prev (row i − 1) and cur (row i). Fill cur from left to right, then swap the two. The last value of prev is the answer.

Core Validity Invariant

A cell is correct when its last letters are handled: a match copies the diagonal for free, and a mismatch pays 1 for the cheapest of insert, delete or replace.

01

Problem

You have two words, word1 and word2. Find the fewest operations that turn word1 into word2.

You may do three things to a word: insert one letter, delete one letter, or replace one letter with another. Each operation counts as 1, whatever letters are involved.

Input

Two strings word1 and word2. Either one can be empty.

Output

A single number: the fewest operations that turn word1 into word2.

Example 1
Input: word1 = "horse", word2 = "ros"
Output: 3

Replace h with r (rorse), delete r (rose), delete e (ros). No route uses only two operations.

Example 2
Input: word1 = "intention", word2 = "execution"
Output: 5

Delete t, replace i with e, replace n with x, replace n with c, and insert u. Five operations.

Constraints
  • • 0 ≤ word1.length, word2.length ≤ 500
  • • word1 and word2 consist of lowercase English letters.
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    If the last letters of the two words are the same, does that last letter need an operation at all?

  2. 2.

    If the last letters differ, which of the three operations can fix them, and what does each one leave behind?

  3. 3.

    After one operation, which smaller pair of words is left to solve? Is it shorter in word1, in word2, or both?

  4. 4.

    How many operations turn an empty word into a word of 3 letters? How many turn a word of 3 letters into an empty word?

  5. 5.

    Two words of length 5 and 3 share no letter at all. What is the fewest number of operations, without working it out letter by letter?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceRecurse on (i, j): a match is free, otherwise take the cheapest of three movesO(3^(N + M))O(N + M)
BetterA table with one cell per pair of prefixes; each cell is filled once from three cells before itO(N · M)O(N · M)
OptimalA cell reads only the row above and the cell to its left, so two rows are enoughO(N · M)O(M)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “fewest operations”A minimum over several choices. The table keeps the cheapest value for each pair of prefixes.
  • “insert, delete or replace”Three moves on the last letter, so each cell reads three cells. This is what makes it edit distance.
  • “turn word1 into word2”Two strings, so the table has one axis for each string.
Two strings+minimum over insert / delete / replace+each move costs 1→DP — Strings, Edit distance (minimum of insert, delete, replace)

This is the anchor of the sub-pattern. Each cell takes the cheapest of three moves on the last letters, and a match costs nothing. The next questions remove moves: Minimum ASCII Delete Sum keeps only the delete moves and weights each letter, and Interleaving String only asks whether each cell can be true. LCS looks similar, but it has no replace move, so it is not this table.

10

Don't make this mistake

Pattern confusion: n + m − 2 × LCS
✗ return word1.size() + word2.size() - 2 * lcs(word1, word2);
✓ dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]); // when the letters differ

LCS counts only insert and delete. A replace is one delete plus one insert there, so it costs 2, but it costs 1 here. On horse and ros the longest common subsequence has 2 letters (for example os), so n + m − 2 × LCS = 5 + 3 − 4 = 4. The real answer is 3: replace h with r, delete r, delete e.

Base cases set to 0
✗ for (int i = 0; i <= n; i++) dp[i][0] = 0; for (int j = 0; j <= m; j++) dp[0][j] = 0;
✓ for (int i = 0; i <= n; i++) dp[i][0] = i; for (int j = 0; j <= m; j++) dp[0][j] = j;

Turning an empty word1 into j letters takes j inserts, not 0. With the base at 0, horse → ros gives 2 instead of 3, and an empty word1 → ab gives 0 instead of 2.

Charging 1 for a match
✗ dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]); // always, even when the letters match
✓ if (word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1]; else dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]);

Matching letters are kept for free. Charging 1 for them makes a → a cost 1 instead of 0.

Overwriting one row and losing the diagonal
✗ for (int j = 1; j <= m; j++) dp[j] = word1[i-1] == word2[j-1] ? dp[j-1] : 1 + min({dp[j-1], dp[j], dp[j-1]});
✓ Keep two rows (prev and cur), or save the old diagonal before it is overwritten.

When we reach column j, dp[j − 1] has already been overwritten with the new row. It is the cell to the left, not the cell above-left, so the diagonal is lost. On horse → ros this gives 6 instead of 3.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like DP — Strings translate into production architectures and low-level memory mechanics.