Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

583. Delete Operation for Two Strings - Leetcode Solution

Code Implementation

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        m, n = len(word1), len(word2)
        dp = [[0]*(n+1) for _ in range(m+1)]
        for i in range(m):
            for j in range(n):
                if word1[i] == word2[j]:
                    dp[i+1][j+1] = dp[i][j] + 1
                else:
                    dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j])
        lcs = dp[m][n]
        return (m - lcs) + (n - lcs)
      
class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size(), n = word2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (word1[i] == word2[j])
                    dp[i + 1][j + 1] = dp[i][j] + 1;
                else
                    dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]);
            }
        }
        int lcs = dp[m][n];
        return (m - lcs) + (n - lcs);
    }
};
      
class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length(), n = word2.length();
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (word1.charAt(i) == word2.charAt(j))
                    dp[i + 1][j + 1] = dp[i][j] + 1;
                else
                    dp[i + 1][j + 1] = Math.max(dp[i][j + 1], dp[i + 1][j]);
            }
        }
        int lcs = dp[m][n];
        return (m - lcs) + (n - lcs);
    }
}
      
var minDistance = function(word1, word2) {
    let m = word1.length, n = word2.length;
    let dp = Array.from({length: m+1}, () => Array(n+1).fill(0));
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (word1[i] === word2[j]) {
                dp[i+1][j+1] = dp[i][j] + 1;
            } else {
                dp[i+1][j+1] = Math.max(dp[i][j+1], dp[i+1][j]);
            }
        }
    }
    let lcs = dp[m][n];
    return (m - lcs) + (n - lcs);
};
      

Problem Description

You are given two strings, word1 and word2. Your task is to determine the minimum number of delete operations needed to make the two strings equal. In one operation, you can delete any character from either string.

  • Both strings consist of lowercase English letters.
  • You can delete from either string, but cannot insert or substitute characters.
  • The goal is to make both strings identical using the smallest number of deletions.
  • There is always at least one valid solution.
  • You may not reuse deleted elements or perform any other operations except deletion.

Thought Process

At first glance, it might seem like we need to compare each character in word1 to each character in word2 and decide whether to keep or delete it. A brute-force approach would try all possible deletions, but this quickly becomes infeasible for longer strings due to the exponential number of possibilities.

To optimize, notice that the only way to make the strings equal is to delete characters until they share the same sequence. The longest common subsequence (LCS) of the two strings is the sequence we want to keep. All other characters must be deleted. So, the problem reduces to finding the length of the LCS, and then deleting all characters that are not part of it from both strings.

This insight transforms the problem from a brute-force search into a classic dynamic programming problem (LCS), which is much more efficient.

Solution Approach

  • Step 1: Find the Longest Common Subsequence (LCS)
    • Use dynamic programming to compute the LCS length between word1 and word2.
    • Create a 2D array dp where dp[i][j] represents the length of the LCS between the first i characters of word1 and the first j characters of word2.
    • If word1[i-1] == word2[j-1], then dp[i][j] = dp[i-1][j-1] + 1.
    • Otherwise, dp[i][j] = max(dp[i-1][j], dp[i][j-1]).
  • Step 2: Calculate the Minimum Number of Deletions
    • After finding the length of the LCS (lcs), the minimum deletions required is:
      • (len(word1) - lcs) + (len(word2) - lcs)
    • This is because all characters not in the LCS must be deleted from both strings.
  • Step 3: Implement the Algorithm
    • Use nested loops to fill the dp table.
    • Return the calculated minimum number of deletions.

This approach is efficient and leverages the structure of the problem to avoid redundant calculations.

Example Walkthrough

Let's take word1 = "sea" and word2 = "eat" as an example.

  1. Compute the LCS:
    • The possible common subsequences are: "e", "a", "ea".
    • The longest is "ea" (length 2).
  2. Calculate deletions:
    • len(word1) = 3, len(word2) = 3, lcs = 2
    • Minimum deletions = (3 - 2) + (3 - 2) = 2
  3. Trace:
    • Delete 's' from "sea" and 't' from "eat" to get "ea" in both strings.

This matches the expected output.

Time and Space Complexity

  • Brute-force approach:
    • Would try all possible deletions, leading to exponential time complexity: O(2^(m+n)), where m and n are the lengths of the two strings.
  • Optimized DP approach:
    • Filling the dp table takes O(m * n) time, as we compute each cell once.
    • Space complexity is also O(m * n) for the dp table.
    • Further optimization can reduce space to O(min(m, n)) if only two rows or columns are kept at a time.

Summary

The key to efficiently solving the "Delete Operation for Two Strings" problem is recognizing its connection to the Longest Common Subsequence (LCS). By finding the LCS, we identify the characters to keep and delete all others, minimizing the number of operations. The dynamic programming approach is both elegant and efficient, reducing a seemingly complex problem to a manageable and well-known subproblem.