You are given a 0-indexed string word
.
In one operation, you can pick any index i
of word
and change word[i]
to any lowercase English letter.
Return the minimum number of operations needed to remove all adjacent almost-equal characters from word
.
Two characters a
and b
are almost-equal if a == b
or a
and b
are adjacent in the alphabet.
Example 1:
Input: word = "aaaaa" Output: 2 Explanation: We can change word into "acaca" which does not have any adjacent almost-equal characters. It can be shown that the minimum number of operations needed to remove all adjacent almost-equal characters from word is 2.
Example 2:
Input: word = "abddez" Output: 2 Explanation: We can change word into "ybdoez" which does not have any adjacent almost-equal characters. It can be shown that the minimum number of operations needed to remove all adjacent almost-equal characters from word is 2.
Example 3:
Input: word = "zyxyxyz" Output: 3 Explanation: We can change word into "zaxaxaz" which does not have any adjacent almost-equal characters. It can be shown that the minimum number of operations needed to remove all adjacent almost-equal characters from word is 3.
Constraints:
1 <= word.length <= 100
word
consists only of lowercase English letters.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 strategy for this problem is to check every possible combination of character removals. We'll look at each pair of adjacent characters and, if they are 'almost equal', we'll explore what happens if we remove the first one, the second one, or neither.
Here's how the algorithm would work step-by-step:
def remove_adjacent_almost_equal_characters_brute_force(input_string):
shortest_string = input_string
def find_almost_equal_adjacent_indices(current_string):
indices = []
for index in range(len(current_string) - 1):
if abs(ord(current_string[index]) - ord(current_string[index + 1])) == 1:
indices.append(index)
return indices
def solve(current_string):
nonlocal shortest_string
adjacent_indices = find_almost_equal_adjacent_indices(current_string)
if not adjacent_indices:
# No almost-equal chars exist, check if shortest.
if len(current_string) < len(shortest_string):
shortest_string = current_string
return
for index_to_remove in adjacent_indices:
# Explore removing each possible char.
new_string = current_string[:index_to_remove] + current_string[index_to_remove+1:]
solve(new_string)
solve(input_string)
return shortest_string
The core idea is to go through the text character by character, deciding at each step whether to keep a character or remove it. The trick is to remove a character only if it is almost equal to the character immediately following it.
Here's how the algorithm would work step-by-step:
def remove_adjacent_almost_equal_characters(input_string):
result_string = ""
for char in input_string:
if not result_string:
# The first character is always safe to add.
result_string += char
else:
last_char_in_result = result_string[-1]
# Check if the current char is 'almost equal' to the last one.
if abs(ord(char) - ord(last_char_in_result)) != 1:
# Keep the current character if it's not almost equal.
result_string += char
return result_string
Case | How to Handle |
---|---|
Empty string | Return 0 since there are no characters to remove. |
String with a single character | Return 0 since there are no adjacent characters. |
String with two almost-equal characters | Return 1 since one of them should be removed. |
String with two non-almost-equal characters | Return 0 since no removal is required. |
String with all almost-equal characters (e.g., 'abcba') | The algorithm should greedily remove characters until no adjacent almost-equal characters remain, leading to potentially significant removals. |
Long string where the solution requires many removals, testing performance. | The solution should be optimized to avoid quadratic or exponential time complexity. |
String with ASCII values at the boundaries (0 and 255) that might cause integer under/overflow during subtraction | Use the absolute difference function to ensure correct comparison regardless of the order and to prevent under/overflow. |
A string like 'aaaaaa' where removing adjacent characters does not change the number of 'a' left at the end. | The code must correctly identify that removing 'aa' removes one character effectively and doesn't get stuck at the beginning. |