Given two strings s
and t
, determine if they are both one edit distance apart.
Note:
There are three possible edits to transform one string to another:
Example 1:
Input: s = "ab", t = "acb" Output: true Explanation: We can insert 'c' into s to get t.
Example 2:
Input: s = "", t = "" Output: false Explanation: We need exactly one edit to transform one string into another.
Example 3:
Input: s = "a", t = "" Output: true
Example 4:
Input: s = "", t = "a" Output: true
Example 5:
Input: s = "abc", t = "adc" Output: true
Constraints:
0 <= s.length <= 104
0 <= t.length <= 104
s
and t
consist of lower-case letters, upper-case letters and/or digits.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:
The brute force method for determining if two strings are within one edit distance of each other involves exploring all possible single edits on each string. This means trying every possible insertion, deletion, and replacement to see if any of those changes makes the strings equal. If at least one of these edits results in the two strings being identical, then they are indeed one edit distance away.
Here's how the algorithm would work step-by-step:
def is_one_edit_distance_brute_force(first_string, second_string):
string_length_first = len(first_string)
string_length_second = len(second_string)
# Check if adding a character to first_string makes it equal to second_string
for index in range(string_length_first + 1):
modified_string = first_string[:index] + 'x' + first_string[index:]
if modified_string == second_string:
return True
# Check if deleting a character from first_string makes it equal to second_string
for index in range(string_length_first):
modified_string = first_string[:index] + first_string[index+1:]
if modified_string == second_string:
return True
# Check if replacing a character in first_string makes it equal to second_string
for index in range(string_length_first):
for char_code in range(ord('a'), ord('z') + 1):
replacement_character = chr(char_code)
modified_string = first_string[:index] + replacement_character + first_string[index+1:]
if modified_string == second_string:
return True
# Now, repeat the process for second_string to check edits to second_string
for index in range(string_length_second + 1):
modified_string = second_string[:index] + 'x' + second_string[index:]
if modified_string == first_string:
return True
for index in range(string_length_second):
modified_string = second_string[:index] + second_string[index+1:]
if modified_string == first_string:
return True
# Replacing characters in second_string
for index in range(string_length_second):
for char_code in range(ord('a'), ord('z') + 1):
replacement_character = chr(char_code)
modified_string = second_string[:index] + replacement_character + second_string[index+1:]
if modified_string == first_string:
return True
# Exhausted all options, so return False
return False
The goal is to quickly determine if two words are nearly identical, differing by only one edit. The smart strategy is to identify the first difference and then focus our attention solely on the remaining parts of the words. This avoids unnecessary comparisons when a difference is already found.
Here's how the algorithm would work step-by-step:
def is_one_edit_distance(first_word, second_word):
length_difference = abs(len(first_word) - len(second_word))
if length_difference > 1:
return False
first_word_length = len(first_word)
second_word_length = len(second_word)
index_first_word = 0
index_second_word = 0
difference_found = False
while index_first_word < first_word_length and index_second_word < second_word_length:
if first_word[index_first_word] != second_word[index_second_word]:
# Mark that a difference has been found
difference_found = True
if first_word_length == second_word_length:
# Handles the replacement case
index_first_word += 1
index_second_word += 1
elif first_word_length > second_word_length:
# Handles deletion from first_word
index_first_word += 1
else:
# Handles insertion into first_word
index_second_word += 1
else:
index_first_word += 1
index_second_word += 1
if difference_found:
remaining_first_word = first_word[index_first_word:]
remaining_second_word = second_word[index_second_word:]
# After the difference, remaining parts should match
if remaining_first_word != remaining_second_word:
return False
else:
return True
# No differences found until the end.
if not difference_found:
# Need to check if a single insertion/deletion occurred.
return length_difference == 1
return True
Case | How to Handle |
---|---|
Both strings are null | Treat as zero edits, thus should return false since zero is not one. |
One string is null, the other is not empty | If one string is null and the other has length 1, return true; otherwise return false. |
Both strings are empty | Return false as zero edits do not satisfy 'one edit distance'. |
Strings are identical | Return false because they are zero edits away from each other. |
Length difference is greater than 1 | Return false immediately since more than one insertion/deletion would be required. |
Strings have the same length, but differ by more than one character | Return false since more than one replacement is needed. |
Strings have very long length (potential performance issue) | The algorithm should iterate linearly through the strings, so it scales as O(n). |
Strings contain unicode characters | Character comparison should handle unicode characters correctly in most languages. |