Shifting Letters II

medium prefix sum difference array string

Problem

You are given a string s of lowercase letters and a list of shifts shifts[i] = [start, end, direction]. For each shift, every character from index start to end (inclusive) moves one letter forward in the alphabet when direction = 1 (with 'z' wrapping to 'a'), or one letter backward when direction = 0 (with 'a' wrapping to 'z'). Return the final string after every shift is applied.

Inputs = "abc", shifts = [[0,1,0],[1,2,1],[0,2,1]]
Output"ace"
Net shift per index is [0, +1, +2]: 'a'+0='a', 'b'+1='c', 'c'+2='e'.

def shiftingLetters(s, shifts):
    n = len(s)
    diff = [0] * (n + 1)             # difference array
    for start, end, direction in shifts:
        amt = 1 if direction == 1 else -1
        diff[start] += amt           # open the range
        diff[end + 1] -= amt         # close just past the end
    res = []
    cur = 0
    for i in range(n):
        cur += diff[i]               # prefix sum = net shift at i
        nc = (ord(s[i]) - ord('a') + cur) % 26
        res.append(chr(ord('a') + nc))
    return "".join(res)
function shiftingLetters(s, shifts) {
  const n = s.length;
  const diff = new Array(n + 1).fill(0);   // difference array
  for (const [start, end, direction] of shifts) {
    const amt = direction === 1 ? 1 : -1;
    diff[start] += amt;                     // open the range
    diff[end + 1] -= amt;                   // close just past the end
  }
  const res = [];
  let cur = 0;
  for (let i = 0; i < n; i++) {
    cur += diff[i];                         // prefix sum = net shift
    const nc = ((s.charCodeAt(i) - 97 + cur) % 26 + 26) % 26;
    res.push(String.fromCharCode(97 + nc));
  }
  return res.join("");
}
String shiftingLetters(String s, int[][] shifts) {
    int n = s.length();
    long[] diff = new long[n + 1];          // difference array
    for (int[] sh : shifts) {
        int amt = sh[2] == 1 ? 1 : -1;
        diff[sh[0]] += amt;                 // open the range
        diff[sh[1] + 1] -= amt;             // close just past the end
    }
    char[] res = new char[n];
    long cur = 0;
    for (int i = 0; i < n; i++) {
        cur += diff[i];                     // prefix sum = net shift
        int nc = (int) (((s.charAt(i) - 'a' + cur) % 26 + 26) % 26);
        res[i] = (char) ('a' + nc);
    }
    return new String(res);
}
string shiftingLetters(string s, vector<vector<int>>& shifts) {
    int n = s.size();
    vector<long long> diff(n + 1, 0);        // difference array
    for (auto& sh : shifts) {
        int amt = sh[2] == 1 ? 1 : -1;
        diff[sh[0]] += amt;                 // open the range
        diff[sh[1] + 1] -= amt;             // close just past the end
    }
    long long cur = 0;
    for (int i = 0; i < n; i++) {
        cur += diff[i];                     // prefix sum = net shift
        int nc = ((s[i] - 'a' + cur) % 26 + 26) % 26;
        s[i] = 'a' + nc;
    }
    return s;
}
Time: O(n + m) Space: O(n)