You are given a string s
of lowercase English letters and a 2D integer array shifts
where shifts[i] = [start_i, end_i, direction_i]
. For every i
, shift the characters in s
from the index start_i
to the index end_i
(inclusive) forward if direction_i = 1
, or shift the characters backward if direction_i = 0
.
Shifting a character forward means replacing it with the next letter in the alphabet (wrapping around so that 'z'
becomes 'a'
). Similarly, shifting a character backward means replacing it with the previous letter in the alphabet (wrapping around so that 'a'
becomes 'z'
).
Return the final string after all such shifts to s
are applied.
Example 1:
Input: s = "abc", shifts = [[0,1,0],[1,2,1],[0,2,1]]
Output: "ace"
Explanation:
Firstly, shift the characters from index 0 to index 1 backward. Now s = "zac".
Secondly, shift the characters from index 1 to index 2 forward. Now s = "zbd".
Finally, shift the characters from index 0 to index 2 forward. Now s = "ace".
Example 2:
Input: s = "dztz", shifts = [[0,0,0],[1,1,1]]
Output: "catz"
Explanation:
Firstly, shift the characters from index 0 to index 0 backward. Now s = "cztz".
Finally, shift the characters from index 1 to index 1 forward. Now s = "catz".
Write a function to efficiently compute the final string after applying all shifts.
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 modifies a word letter by letter according to instructions. For each instruction, we go through the specified portion of the word and shift the letters as directed, handling letter wrapping as needed.
Here's how the algorithm would work step-by-step:
def shifting_letters_two_brute_force(word, shifts):
modified_word = list(word)
for shift_instruction in shifts:
start_index = shift_instruction[0]
end_index = shift_instruction[1]
shift_direction = shift_instruction[2]
# Iterate over the section to be modified.
for index in range(start_index, end_index + 1):
original_character = modified_word[index]
original_ascii_value = ord(original_character)
# Apply the shift based on the specified direction.
if shift_direction == 1:
new_ascii_value = original_ascii_value + 1
if new_ascii_value > ord('z'):
new_ascii_value = ord('a')
else:
new_ascii_value = original_ascii_value - 1
# Wrap around if we go past 'a'.
if new_ascii_value < ord('a'):
new_ascii_value = ord('z')
modified_word[index] = chr(new_ascii_value)
return "".join(modified_word)
We need to modify a string of letters based on a series of shifts. Instead of applying each shift individually, which would be slow, we can calculate the total shift for each letter and then apply it all at once. This dramatically reduces the number of operations.
Here's how the algorithm would work step-by-step:
def shiftingLetters(string, shifts):
string_length = len(string)
shift_values = [0] * string_length
for start, end, direction in shifts:
shift_direction = 1 if direction == 1 else -1
shift_values[start] += shift_direction
if end + 1 < string_length:
shift_values[end + 1] -= shift_direction
cumulative_shift = 0
shifted_string = list(string)
# Accumulate shift values to get net shift
for index in range(string_length):
cumulative_shift += shift_values[index]
# Apply shifting to each letter
original_char_code = ord(string[index]) - ord('a')
new_char_code = (original_char_code + cumulative_shift) % 26
# Wrapping logic implemented here.
if new_char_code < 0:
new_char_code += 26
shifted_string[index] = chr(new_char_code + ord('a'))
return "".join(shifted_string)
Case | How to Handle |
---|---|
Null or empty string s | Return an empty string or throw an exception, depending on requirements; the provided operations array is not applicable. |
Null or empty operations array | Return the original string since no shifts are specified. |
Empty operations within the operations array | Skip the empty operation (treat as a no-op) or raise an exception, depending on problem constraints. |
Large operations array size exceeding memory limits | Consider using an in-place modification of the string or a more memory-efficient data structure. |
Start index equals end index in an operation | The substring affected by this operation is just a single character, so apply the shift directly. |
Start index greater than end index in an operation | Treat this as an invalid input and either throw an error or swap start and end, depending on the expected behavior. |
Absolute value of shift is extremely large causing integer overflow | Use modulo operation with 26 to constrain the shift value within the alphabet range. |
Operations overlap, causing multiple shifts to the same character | Accumulate all the shifts for each character, then apply a single cumulative shift modulo 26 to each character at the end. |