🧠
Brute Force (Pure Recursion)
💡 Starting with brute force helps understand the problem's recursive structure and why naive recursion is inefficient due to repeated subproblems.
Intuition
Try all ways to delete characters from either string until they match, summing ASCII values of deleted characters.
Algorithm
- If either string is empty, return sum of ASCII values of the other string.
- If last characters match, recurse on both strings without deleting.
- Otherwise, recurse by deleting last character from s1 or s2 and add its ASCII value.
- Return the minimum cost from the two deletion options.
💡 The recursion is straightforward but leads to exponential calls due to overlapping subproblems.
Recurrence:dp(i,j) = if s1[i-1] == s2[j-1] then dp(i-1,j-1) else min(dp(i-1,j) + ASCII(s1[i-1]), dp(i,j-1) + ASCII(s2[j-1]))
def minimumDeleteSum(s1: str, s2: str) -> int:
def helper(i, j):
if i == 0 and j == 0:
return 0
if i == 0:
return sum(ord(c) for c in s2[:j])
if j == 0:
return sum(ord(c) for c in s1[:i])
if s1[i-1] == s2[j-1]:
return helper(i-1, j-1)
else:
return min(helper(i-1, j) + ord(s1[i-1]), helper(i, j-1) + ord(s2[j-1]))
return helper(len(s1), len(s2))
# Example usage:
if __name__ == '__main__':
print(minimumDeleteSum("sea", "eat")) # Output: 231
Line Notes
def helper(i, j):Defines recursive helper to compute cost for prefixes s1[:i], s2[:j]
if i == 0 and j == 0:Base case: both strings empty, no cost
if i == 0:If s1 empty, cost is sum of ASCII of s2 prefix
if s1[i-1] == s2[j-1]:If last chars match, no deletion needed, recurse on smaller prefixes
public class Solution {
public int minimumDeleteSum(String s1, String s2) {
return helper(s1, s2, s1.length(), s2.length());
}
private int helper(String s1, String s2, int i, int j) {
if (i == 0 && j == 0) return 0;
if (i == 0) {
int sum = 0;
for (int k = 0; k < j; k++) sum += s2.charAt(k);
return sum;
}
if (j == 0) {
int sum = 0;
for (int k = 0; k < i; k++) sum += s1.charAt(k);
return sum;
}
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
return helper(s1, s2, i - 1, j - 1);
} else {
return Math.min(helper(s1, s2, i - 1, j) + s1.charAt(i - 1),
helper(s1, s2, i, j - 1) + s2.charAt(j - 1));
}
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.minimumDeleteSum("sea", "eat")); // 231
}
}
Line Notes
private int helper(String s1, String s2, int i, int j)Recursive helper for prefixes s1[0..i-1], s2[0..j-1]
if (i == 0 && j == 0) return 0;Base case: both empty strings
for (int k = 0; k < j; k++) sum += s2.charAt(k);Sum ASCII values if s1 empty
if (s1.charAt(i - 1) == s2.charAt(j - 1))If last chars match, recurse without deletion
#include <iostream>
#include <string>
#include <numeric>
using namespace std;
class Solution {
public:
int minimumDeleteSum(string s1, string s2) {
return helper(s1, s2, s1.size(), s2.size());
}
private:
int helper(const string& s1, const string& s2, int i, int j) {
if (i == 0 && j == 0) return 0;
if (i == 0) return accumulate(s2.begin(), s2.begin() + j, 0);
if (j == 0) return accumulate(s1.begin(), s1.begin() + i, 0);
if (s1[i - 1] == s2[j - 1]) {
return helper(s1, s2, i - 1, j - 1);
} else {
return min(helper(s1, s2, i - 1, j) + s1[i - 1],
helper(s1, s2, i, j - 1) + s2[j - 1]);
}
}
};
int main() {
Solution sol;
cout << sol.minimumDeleteSum("sea", "eat") << endl; // 231
return 0;
}
Line Notes
int helper(const string& s1, const string& s2, int i, int j)Recursive helper for prefixes
if (i == 0 && j == 0) return 0;Base case both empty
return accumulate(s2.begin(), s2.begin() + j, 0);Sum ASCII if s1 empty
if (s1[i - 1] == s2[j - 1])If chars match, recurse without deletion
function minimumDeleteSum(s1, s2) {
function helper(i, j) {
if (i === 0 && j === 0) return 0;
if (i === 0) return [...s2.slice(0, j)].reduce((a, c) => a + c.charCodeAt(0), 0);
if (j === 0) return [...s1.slice(0, i)].reduce((a, c) => a + c.charCodeAt(0), 0);
if (s1[i - 1] === s2[j - 1]) {
return helper(i - 1, j - 1);
} else {
return Math.min(helper(i - 1, j) + s1.charCodeAt(i - 1),
helper(i, j - 1) + s2.charCodeAt(j - 1));
}
}
return helper(s1.length, s2.length);
}
console.log(minimumDeleteSum("sea", "eat")); // 231
Line Notes
function helper(i, j)Recursive helper for prefixes s1[0..i-1], s2[0..j-1]
if (i === 0 && j === 0) return 0;Base case both empty
return [...s2.slice(0, j)].reduce((a, c) => a + c.charCodeAt(0), 0);Sum ASCII if s1 empty
if (s1[i - 1] === s2[j - 1])If chars match, recurse without deletion
TimeO(2^(m+n))
SpaceO(m+n) due to recursion stack
Each call branches into two calls unless characters match, leading to exponential calls.
💡 For strings of length 10, this could mean over a million calls, which is impractical.
Interview Verdict: TLE
This approach is too slow for large inputs but is essential to understand the problem's recursive nature.