2381. Shifting Letters II
2381. Shifting Letters II
[Problem]
Intuition
- The problem involves shifting characters in a string based on multiple range-based operations.
- To handle these efficiently, we can use a prefix sum array to compute the cumulative shifts for each character.
- This avoids recalculating shifts for overlapping ranges, ensuring optimal performance.
Approach
- Create a prefix array
shiftArray
to mark thestart
andend+1
of each shift operation. Increment for right shifts (
+1
) and decrement for left shifts (-1
).use the prefix array
shiftArray
to calculate the cumulative shift for each character by iterating over the array.- Normalize the cumulative shift to fall within
[0, 25]
using%26
to handle large or negative shifts.- How does this work?
- Convert Character to Index:
a
->0
,b
->1
,c
->2
and so on(ch - 'a')
- Add the shift (delta) to the index.
- Use mod 26 (
% 26
) to ensure it wraps around within the alphabet. - If the result is negative, add 26 to bring it back into the valid range.
- Convert Back to Character
- Add
a
to the shifted index to get the new character. - To ensure the shift wraps around the alphabet, we take the
total shift %26
(since there are 26 letters). - If the shift is negative (from left shifts), add
26
to make it positive.
1 2 3 4 5 6 7 8 9 10 11 12
private char findNextChar(char ch, int delta) { // calculate the shifted character int shifted = (ch - 'a' + delta) % 26; // handle negative shifts if (shifted < 0) { shifted += 26; } // convert back to character return (char) ('a' + shifted); }
- How does this work?
Complexity Analysis
- Time Complexity: O(n + m)
n
: length of the string, processing prefix array and modifying characters.m
: total shifts, for processing theshifts
array.
- Space Complexity: O(n)
prefix
array
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
public String shiftingLetters(String s, int[][] shifts) {
int sLen = s.length();
// use an array to track shifts for each index
int[] shiftArray = new int[sLen + 1]; // Extra space to handle end+1
// computer `shiftArray` based on the shifts
for (int[] shift : shifts) {
int start = shift[0];
int end = shift[1];
int delta = shift[2] == 0 ? -1 : 1;
shiftArray[start] += delta; // increment shift at start
shiftArray[end + 1] -= delta; // decrement shift after end
}
// Accumulate the shifts to get final shift for each index
int cumulativeShift = 0;
for (int i = 0; i < sLen; i++) {
cumulativeShift += shiftArray[i];
shiftArray[i] = cumulativeShift;
}
StringBuilder sb = new StringBuilder(sLen);
for (int i = 0; i < sLen; i++) {
int delta = shiftArray[i];
char ch = findNextChar(s.charAt(i), delta); // adjust the character
sb.append(ch);
}
return sb.toString();
}
private char findNextChar(char ch, int delta) {
// calculate the shifted character
int shifted = (ch - 'a' + delta) % 26;
// handle negative shifts
if (shifted < 0) {
shifted += 26;
}
// convert back to character
return (char) ('a' + shifted);
}
}
This post is licensed under CC BY 4.0 by the author.