Shifting Letters II

Updated on 14 July, 2025
Shifting Letters II header image

Problem Statement

You are given a string s made up of lowercase English letters and a 2D integer array named shifts. Each element of shifts, represented as [starti, endi, directioni], dictates a specific operation on s. According to the value of directioni, every character in the substring of s from starti to endi will be modified:

  • If directioni = 1, shift the characters forward by one step in the alphabetical sequence.
  • If directioni = 0, shift the characters backward by one step.

Forward shifting a character means moving to the next letter in the alphabet, and wrapping around so that 'z' becomes 'a'. Conversely, backward shifting means moving to the previous letter, with 'a' wrapping around to become 'z'.

Your task is to apply all the shifts as specified by shifts to the string s and return the final modified string.

Examples

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".

Constraints

  • 1 <= s.length, shifts.length <= 5 * 104
  • shifts[i].length == 3
  • 0 <= starti <= endi < s.length
  • 0 <= directioni <= 1
  • s consists of lowercase English letters.

Approach and Intuition

To solve this problem, we need to efficiently manage multiple shifts on different ranges of the string s. Here are the steps to achieve the solution effectively:

  1. Start by creating an auxiliary array, increment, with the same length as string s. This will track the net shifts applied to each character due to all the shift operations.

  2. Loop through each operation in shifts. For each [starti, endi, directioni]:

    • Increase the increment[starti] by 1 if directioni == 1 (indicating a forward shift) or decrease it by 1 if directioni == 0 (indicating a backward shift).
    • If there is an index after endi (i.e., endi + 1 < length of s), then counteract the earlier increment/decrement to neutralize the effect of shifts beyond endi.
  3. Convert the increments into actual net shifts for each character:

    • Utilize a prefix sum approach to accumulate shifts for each character. This means that each index i will gather all increments up to that index, which gives the final amount of shift needed for the character at i.
  4. Apply the net shifts to the string:

    • For each character, calculate its new shifted position based on its ASCII value adjusted by the net shift value.
    • Use modular arithmetic to wrap around the alphabet if necessary (i.e., going from 'z' to 'a', or 'a' to 'z').

In terms of efficiency, this approach only requires two passes over the string, and adjustments per the shifts array, resulting in a time complexity approximately linear to the size of s plus the number of shifts, which is efficient given the problem constraints.

Solutions

  • C++
cpp
class Solution {
public:
    string shiftingLetters(string str, vector<vector<int>>& operations) {
        int length = str.size();
        vector<int> shift(length, 0); // Initialize shift array
    
        for (auto op : operations) {
            int factor = (op[2] == 1) ? 1 : -1; // Determine the shift direction
            shift[op[0]] += factor;             // Apply shift at the start index
            if (op[1] + 1 < length) {
                shift[op[1] + 1] -= factor;     // Reverse the shift after the end index
            }
        }
    
        string modifiedStr(length, ' ');
        int accumulatedShift = 0;
    
        for (int i = 0; i < str.size(); i++) {
            accumulatedShift = (accumulatedShift + shift[i]) % 26; // Update total shifts, within alphabet bounds
            if (accumulatedShift < 0)
                accumulatedShift += 26; // Ensure `accumulatedShift` is positive
    
            // Calculate the new character by shifting `str[i]`
            modifiedStr[i] = 'a' + (str[i] - 'a' + accumulatedShift) % 26;
        }
    
        return modifiedStr;
    }
};

This summary explains a C++ solution for modifying a string using a set of operations, where each operation shifts a substring of characters to the right or left within the alphabet. Ensure your development environment supports C++ and is set up to compile and run C++ code effectively.

Key Elements of the Solution:

  • The function shiftingLetters receives a string and a series of operations detailing the range of indices and direction of the shift.
  • The initial step involves creating a shift array that matches the size of the string with initial values set to zero.
  • Operations are processed to compute the amount and direction of the shift for each position in the string. This shift is recorded in the shift array.
  • Post initializing the shift values, accumulate the shifts in a forward pass through the string to manage the net effect where the operation ranges overlap.
  • For each character in the string, calculate its new position in the alphabet using accumulated shifts. Adjustments are made to handle overflow (characters cycling through 'z' back to 'a').
  • Finally, convert the index-shifted values back to characters forming the modified string.

Considerations:

  • Utilize the modulo operation to manage the character cycling within the alphabetic range.
  • Treat negative values carefully to maintain proper index positions within this cyclic alphabet.
  • The solution leverages the prefix sum approach to transform the shift operations into a manageable form for string modification - a standard technique to handle range updates efficiently.

By grasping this method, you will effectively manipulate strings using shift operations, commonly needed in parsing and cryptography tasks. Be sure to test the solution with various input cases to verify accuracy and performance.

  • Java
java
class Solution {
    
    public String modifyLetters(String inputString, int[][] shiftOperations) {
        int strLength = inputString.length();
        int[] alterArray = new int[strLength]; // Create array to store net shifts
    
        // Construct the shift difference array
        for (int[] operation : shiftOperations) {
            if (operation[2] == 1) { // Shift right
                alterArray[operation[0]]++;
                if (operation[1] + 1 < strLength) {
                    alterArray[operation[1] + 1]--;
                }
            } else { // Shift left
                alterArray[operation[0]]--;
                if (operation[1] + 1 < strLength) {
                    alterArray[operation[1] + 1]++;
                }
            }
        }
    
        StringBuilder modifiedString = new StringBuilder(inputString);
        int accumulatedShifts = 0;
    
        // Modify the characters in the input string
        for (int i = 0; i < strLength; i++) {
            accumulatedShifts = (accumulatedShifts + alterArray[i]) % 26; // Keep shifts in range of alphabet
            if (accumulatedShifts < 0) accumulatedShifts += 26; // Correct for negative shift values
    
            // Compute new character and set it
            char newChar = (char) ('a' +
                ((inputString.charAt(i) - 'a' + accumulatedShifts) % 26));
            modifiedString.setCharAt(i, newChar);
        }
    
        return modifiedString.toString();
    }
}

In this Java solution for the problem "Shifting Letters II," the goal is to modify a string based on a set of shift operations provided as input. Each operation specifies a substring (by start and end indices) and the direction (left or right) for the shift. Here's how the solution is structured:

  • Start by intializing an array alterArray to hold the net effect of all shifts on each character position in the string.
  • Loop through each operation in the shiftOperations array to build the alterArray. Increment or decrement values at the start index and, if needed, adjust the position just past the end index to correct the range of the shift.
  • Construct a new StringBuilder from the input string to facilitate character modification.
  • Iterate over the characters of the input string, applying the cumulative effect of shifts stored in alterArray to calculate the new character positions.
  • Correct for shifts that result in negative values or exceed the length of the alphabet (26 letters), ensuring that shifts wrap around correctly.
  • Assemble and return the modified string by applying the net shifts to each character, computing their new positions within the bounds of the alphabet.

By maintaining the accumulated shifts and using an effective approach to apply these shifts to the string, the solution efficiently modifies the input string according to the described operations without directly manipulating the string multiple times, which would be computationally expensive. Thus, this method is both time and space efficient.

  • Python
python
class Solution:
    def rotateLetters(self, str_input: str, range_shifts: list[list[int]]) -> str:
        length = len(str_input)
        shifts = [0] * length  # Setup array initialized to zero
    
        # Handling shift ranges
        for shift in range_shifts:
            start, end, direction = shift
            increment = 1 if direction == 1 else -1
            shifts[start] += increment
            if end + 1 < length:
                shifts[end + 1] -= increment
    
        transformed_str = list(str_input)
        cumulative_shift = 0
    
        # Transform characters according to shifts
        for i in range(length):
            cumulative_shift = (cumulative_shift + shifts[i]) % 26
            normalized_shift = cumulative_shift if cumulative_shift >= 0 else cumulative_shift + 26
            new_character = chr((ord(str_input[i]) - ord('a') + normalized_shift) % 26 + ord('a'))
            transformed_str[i] = new_character
    
        return "".join(transformed_str)

The solution provided outlines a method to apply character shifting operations to a string based on a list of range shifts. Here's a breakdown of how this code works:

  • The rotateLetters function takes two parameters: str_input, the string to be manipulated, and range_shifts, which specifies the start and end indices along with the direction of shift (positive for right and negative for left) for each range.

  • Initializes an array shifts of the same length as str_input filled with zeros. This array is used to record the net effect of all shifts at each index of the string.

  • Iterates over the range_shifts to populate the shifts array. For each shift instruction:

    • Adjusts the shifts array at the start index by adding or subtracting 1 based on the shift direction.
    • Decreases the effect of the shift right after the end index by adjusting the shifts array at end + 1 (if it's within bounds), which helps in resolving the range effect of the shift efficiently.
  • Transforms the input string into a list transformed_str to facilitate character replacement. Then, it applies cumulative shifts while iterating through the string. Each character in the string is adjusted according to the cumulative shift calculated modulo 26 (to wrap around the alphabet).

  • The cumulative shift for each character is adjusted if necessary to ensure it's non-negative, and the character from str_input is then shifted accordingly. The transformed characters are stored back into transformed_str.

  • Finally, the list is joined back into a string and returned.

This solution leverages the prefix sum technique (using a differential array with shifts to handle cumulative effects of multiple range-based shifts efficiently) and handles character wrapping within the alphabet using modulo operations.

Comments

No comments yet.