Shifting Letters
MediumUpdated: Jun 28, 2025
Practice on:
Problem
You are given a string s of lowercase English letters and an integer array shifts of the same length.
Call the shift() of a letter, the next letter in the alphabet, (wrapping around so that 'z' becomes 'a').
- For example,
shift('a') = 'b',shift('t') = 'u', andshift('z') = 'a'.
Now for each shifts[i] = x, we want to shift the first i + 1 letters of s, x times.
Return the final string after all such shifts to s are applied.
Examples
Example 1
Input: s = "abc", shifts = [3,5,9]
Output: "rpl"
Explanation: We start with "abc".
After shifting the first 1 letters of s by 3, we have "dbc".
After shifting the first 2 letters of s by 5, we have "igc".
After shifting the first 3 letters of s by 9, we have "rpl", the answer.
Example 2
Input: s = "aaa", shifts = [1,2,3]
Output: "gfd"
Constraints
1 <= s.length <= 10^5sconsists of lowercase English letters.shifts.length == s.length0 <= shifts[i] <= 10^9
Solution
Method 1 – Prefix Sum from Right
Intuition
To efficiently apply multiple overlapping shifts, we can process the shifts array from right to left, accumulating the total shifts needed for each character. This way, each character is shifted by the sum of all relevant shifts, avoiding repeated work.
Approach
- Initialize a variable
totalto 0 to keep track of cumulative shifts. - Iterate from the end of the
shiftsarray to the start:
- Add
shifts[i]tototal. - For each character
s[i], shift it bytotal % 26positions. - Store the shifted character in the answer.
- Join and return the final shifted string.
Code
C++
class Solution {
public:
string shiftingLetters(string s, vector<int>& shifts) {
int n = s.size();
vector<char> ans(n);
long long total = 0;
for (int i = n - 1; i >= 0; --i) {
total = (total + shifts[i]) % 26;
ans[i] = 'a' + (s[i] - 'a' + total) % 26;
}
return string(ans.begin(), ans.end());
}
};
Go
func shiftingLetters(s string, shifts []int) string {
n := len(s)
ans := make([]byte, n)
total := 0
for i := n - 1; i >= 0; i-- {
total = (total + shifts[i]) % 26
ans[i] = byte('a' + (int(s[i]-'a')+total)%26)
}
return string(ans)
}
Java
class Solution {
public String shiftingLetters(String s, int[] shifts) {
int n = s.length();
char[] ans = new char[n];
long total = 0;
for (int i = n - 1; i >= 0; --i) {
total = (total + shifts[i]) % 26;
ans[i] = (char)('a' + (s.charAt(i) - 'a' + (int)total) % 26);
}
return new String(ans);
}
}
Kotlin
class Solution {
fun shiftingLetters(s: String, shifts: IntArray): String {
val n = s.length
val ans = CharArray(n)
var total = 0L
for (i in n - 1 downTo 0) {
total = (total + shifts[i]) % 26
ans[i] = 'a' + ((s[i] - 'a' + total.toInt()) % 26)
}
return String(ans)
}
}
Python
class Solution:
def shiftingLetters(self, s: str, shifts: list[int]) -> str:
n = len(s)
ans: list[str] = [''] * n
total: int = 0
for i in range(n - 1, -1, -1):
total = (total + shifts[i]) % 26
ans[i] = chr((ord(s[i]) - ord('a') + total) % 26 + ord('a'))
return ''.join(ans)
Rust
impl Solution {
pub fn shifting_letters(s: String, shifts: Vec<i32>) -> String {
let n = s.len();
let mut ans = vec!['a'; n];
let mut total = 0i64;
let s_bytes = s.as_bytes();
for i in (0..n).rev() {
total = (total + shifts[i] as i64) % 26;
ans[i] = ((s_bytes[i] - b'a' + total as u8) % 26 + b'a') as char;
}
ans.into_iter().collect()
}
}
Complexity
- ⏰ Time complexity:
O(n)— Single pass through the string and shifts. - 🧺 Space complexity:
O(n)— For the answer array.