Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
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').
shift('a') = 'b', shift('t') = 'u', and shift('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.
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 <= 105s consists of lowercase English letters.shifts.length == s.length0 <= shifts[i] <= 109Problem summary: 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', and shift('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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
"abc" [3,5,9]
"aaa" [1,2,3]
replace-all-digits-with-characters)shifting-letters-ii)lexicographically-smallest-string-after-substring-operation)shift-distance-between-two-strings)find-the-k-th-character-in-string-game-i)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #848: Shifting Letters
class Solution {
public String shiftingLetters(String s, int[] shifts) {
char[] cs = s.toCharArray();
int n = cs.length;
long t = 0;
for (int i = n - 1; i >= 0; --i) {
t += shifts[i];
int j = (int) ((cs[i] - 'a' + t) % 26);
cs[i] = (char) ('a' + j);
}
return String.valueOf(cs);
}
}
// Accepted solution for LeetCode #848: Shifting Letters
func shiftingLetters(s string, shifts []int) string {
t := 0
n := len(s)
cs := []byte(s)
for i := n - 1; i >= 0; i-- {
t += shifts[i]
j := (int(cs[i]-'a') + t) % 26
cs[i] = byte('a' + j)
}
return string(cs)
}
# Accepted solution for LeetCode #848: Shifting Letters
class Solution:
def shiftingLetters(self, s: str, shifts: List[int]) -> str:
n, t = len(s), 0
s = list(s)
for i in range(n - 1, -1, -1):
t += shifts[i]
j = (ord(s[i]) - ord("a") + t) % 26
s[i] = ascii_lowercase[j]
return "".join(s)
// Accepted solution for LeetCode #848: Shifting Letters
struct Solution;
impl Solution {
fn shifting_letters(s: String, shifts: Vec<i32>) -> String {
let n = s.len();
let mut s: Vec<char> = s.chars().collect();
let mut prev: u8 = 0;
for i in (0..n).rev() {
prev += (shifts[i] % 26) as u8;
prev %= 26;
s[i] = (b'a' + (s[i] as u8 - b'a' + prev) % 26) as char;
}
s.into_iter().collect()
}
}
#[test]
fn test() {
let s = "abc".to_string();
let shifts = vec![3, 5, 9];
let res = "rpl".to_string();
assert_eq!(Solution::shifting_letters(s, shifts), res);
}
// Accepted solution for LeetCode #848: Shifting Letters
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #848: Shifting Letters
// class Solution {
// public String shiftingLetters(String s, int[] shifts) {
// char[] cs = s.toCharArray();
// int n = cs.length;
// long t = 0;
// for (int i = n - 1; i >= 0; --i) {
// t += shifts[i];
// int j = (int) ((cs[i] - 'a' + t) % 26);
// cs[i] = (char) ('a' + j);
// }
// return String.valueOf(cs);
// }
// }
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.