You are given two strings, s1
and s2
. Your task is to find the minimum ASCII sum of characters that need to be deleted from both strings such that the remaining strings are equal. In other words, you want to make s1
and s2
identical by deleting some characters, and you need to minimize the sum of ASCII values of the deleted characters.
For example:
s1 = "sea"
and s2 = "eat"
, the minimum ASCII sum is 231 because you can delete 's' from s1
(ASCII 115) and 't' from s2
(ASCII 116), resulting in equal strings "ea". The sum is 115 + 116 = 231.s1 = "delete"
and s2 = "leet"
, the minimum ASCII sum is 403. You can delete "dee" from s1
(100 + 101 + 101 = 302) and 'e' from s2
(101), resulting in "let". The sum is 302 + 101 = 403.Explain your approach and provide a code solution. What is the time and space complexity of your solution?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We need to find the smallest sum of character values to delete from two strings so they become identical. The brute force way is to consider all possible deletions from both strings, comparing the results, and picking the option with the lowest sum of deleted character values.
Here's how the algorithm would work step-by-step:
def minimum_ascii_delete_sum_brute_force(string1, string2):
minimum_delete_sum = float('inf')
def calculate_delete_sum(deleted_characters):
delete_sum = 0
for character in deleted_characters:
delete_sum += ord(character)
return delete_sum
def find_minimum_delete_sum(index_string1, index_string2, current_string1, current_string2, deleted_characters):
nonlocal minimum_delete_sum
# If we've reached the end of both strings
if index_string1 == len(string1) and index_string2 == len(string2):
if current_string1 == current_string2:
delete_sum = calculate_delete_sum(deleted_characters)
minimum_delete_sum = min(minimum_delete_sum, delete_sum)
return
# If we've reached the end of the first string
if index_string1 == len(string1):
remaining_characters = string2[index_string2:]
find_minimum_delete_sum(index_string1, len(string2), current_string1, current_string2, deleted_characters + list(remaining_characters))
return
# If we've reached the end of the second string
if index_string2 == len(string2):
remaining_characters = string1[index_string1:]
find_minimum_delete_sum(len(string1), index_string2, current_string1, current_string2, deleted_characters + list(remaining_characters))
return
# Option 1: Delete a character from string1
find_minimum_delete_sum(index_string1 + 1, index_string2, current_string1, current_string2, deleted_characters + [string1[index_string1]])
# Option 2: Delete a character from string2
find_minimum_delete_sum(index_string1, index_string2 + 1, current_string1, current_string2, deleted_characters + [string2[index_string2]])
# Because it could result in the smallest sum
# Option 3: Keep both characters
find_minimum_delete_sum(index_string1 + 1, index_string2 + 1, current_string1 + string1[index_string1], current_string2 + string2[index_string2], deleted_characters)
find_minimum_delete_sum(0, 0, '', '', [])
return minimum_delete_sum
The best way to solve this problem is to use a strategy where we build up the solution gradually. We consider smaller parts of the problem and combine their solutions to solve the overall problem, avoiding redundant calculations. This prevents us from needing to check every single possible deletion.
Here's how the algorithm would work step-by-step:
def minimum_delete_sum(string1, string2):
string1_length = len(string1)
string2_length = len(string2)
# Initialize DP table
dp_table = [[0 for _ in range(string2_length + 1)] for _ in range(string1_length + 1)]
# Fill first row, cost of deleting all of string1
for string1_index in range(1, string1_length + 1):
dp_table[string1_index][0] = dp_table[string1_index - 1][0] + ord(string1[string1_index - 1])
# Fill first column, cost of deleting all of string2
for string2_index in range(1, string2_length + 1):
dp_table[0][string2_index] = dp_table[0][string2_index - 1] + ord(string2[string2_index - 1])
for string1_index in range(1, string1_length + 1):
for string2_index in range(1, string2_length + 1):
# If chars match, no deletion needed
if string1[string1_index - 1] == string2[string2_index - 1]:
dp_table[string1_index][string2_index] = dp_table[string1_index - 1][string2_index - 1]
else:
# Choose min cost of deleting from string1 or string2
dp_table[string1_index][string2_index] = min(
dp_table[string1_index - 1][string2_index] + ord(string1[string1_index - 1]),
dp_table[string1_index][string2_index - 1] + ord(string2[string2_index - 1])
)
# Final value is in the bottom right
return dp_table[string1_length][string2_length]
Case | How to Handle |
---|---|
Both strings are empty | Return 0, as no deletions are needed. |
One string is empty, the other is not | Return the sum of ASCII values of the non-empty string. |
Strings are identical | Return 0, no deletions are necessary. |
Strings have one character each and they are the same | Return 0 since no deletion is necessary. |
Strings have one character each and they are different | Return the sum of the ASCII values of the two characters. |
Strings have maximum allowed length (e.g. 1000 for typical constraints) | Ensure the dynamic programming table doesn't exceed memory limits and the algorithm's time complexity is efficient. |
Strings contain non-ASCII characters | The solution should correctly handle extended ASCII characters or throw an exception if it's designed for basic ASCII. |
Strings contain only a single repeated character each | The DP algorithm should handle this case efficiently, potentially requiring many similar computations. |