Strings · Medium

58. Edit Distance

Topics: String, Dynamic Programming

Solve it on DeVert Campus - free code runner

Problem

Given two strings s1 and s2, find the minimum number of operations (insert, delete, or replace a single character) needed to convert s1 into s2.

Input and output

Input: Two lines: the first contains s1, the second contains s2. Output: Print a single integer - the minimum edit distance between s1 and s2.

Example

Input:
sunday
saturday
Output:
3

Constraints

0 <= |s1|, |s2| <= 1000

Key observation

The base cases (dp[0][j] = j, dp[i][0] = i) represent 'transforming an empty string into a string of length j needs j insertions' (and vice versa for deletions) - these anchor the whole table and are easy to get wrong if rushed.

Intuition

Find the minimum number of single-character insertions, deletions, or replacements needed to transform one string into another. Brute force: Try every possible sequence of insert/delete/replace operations recursively - this branches exponentially without memoization, since the same (i,j) sub-alignment gets recomputed repeatedly across different edit orderings. Optimised: The DP table captures the reusable insight that the edit distance between two prefixes only depends on the edit distances of slightly shorter prefixes (three specific smaller sub-problems) - filling the table bottom-up computes every needed value exactly once, turning exponential search into a table of (|s1|+1)*(|s2|+1) cells.

Approach 1

Recursively compute the edit distance between s1 and s2 by trying all three operations at every mismatched character: insert, delete, or replace, recursing on the corresponding smaller subproblem each time, and taking the minimum plus a base case when either string is exhausted. This directly implements the definition of edit distance but recomputes the exact same (i, j) subproblems exponentially many times. Time: O(3^max(m,n)) Space: O(max(m,n)) recursion depth

Optimal - Bottom-Up DP with Rolling Rows

Build the DP table iteratively from smaller prefixes upward instead of recursing top-down, where dp[i][j] is the edit distance between the first i characters of s1 and first j characters of s2, computed from dp[i-1][j-1], dp[i-1][j], and dp[i][j-1]. Since each row only depends on the previous row, only two rows (or one row updated in place) need to be kept at any time, cutting the space from O(m*n) to O(min(m,n)) while keeping the same O(m*n) time. Time: O(m*n) Space: O(min(m,n))

Better - Recursion with Memoization

Keep the same recursive structure as the brute force but cache the result for each (i, j) pair of remaining prefixes in a memo table, so any subproblem is solved only once. Since there are only O(m*n) distinct (i, j) states and each is solved in O(1) work given its children's cached answers, this collapses the exponential blowup into polynomial time. Time: O(m*n) Space: O(m*n)

Step by step

1. Build a 2D DP table where dp[i][j] means 'the edit distance between the first i characters of s1 and the first j characters of s2'. 2. If the current characters match, no edit is needed here: dp[i][j] = dp[i-1][j-1]. 3. If they don't match, take the best of three possible single-edit choices (insert, delete, replace) and add 1: dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]).

Complexity

Time: O(|s1| * |s2|) - filling the entire DP table, one cell per pair of prefix lengths. Space: O(|s1| * |s2|) for the full table (reducible to O(min(|s1|,|s2|)) with a rolling array, since each row only depends on the row directly above it).

Edge cases

Test with either or both strings empty (0 is an allowed length), s1 equal to s2 (distance 0), strings that share no characters at all, and both strings at length 1000 to check performance.

Interview tip

This is one of the most fundamental DP problems in computer science, underlying real spell-checkers, DNA sequence alignment, and diff tools - be ready to derive the three-way recurrence (insert/delete/replace) from first principles, not just recite it.

All DSA problems