Move Pieces to Obtain a String

Updated on 18 June, 2025
Move Pieces to Obtain a String header image

Problem Statement

In this problem, you are provided with two strings labeled as start and target, both of the same length n. These strings are composed exclusively of the characters: 'L', 'R', and '_'. Here, 'L' and 'R' signify movable pieces with 'L' moving left if there is a direct blank space ('_') to its left, and 'R' moving right if there is a direct blank space ('_') to its right. The character '_' indicates an empty spot, which can be filled by either of the two movable pieces, 'L' or 'R'.

The task is to determine whether you can transform the start string into the target string through any number of valid moves, following the moving rules of 'L' and 'R'. If transformation is feasible under these conditions, return true. If not, return false.

Examples

Example 1

Input:

start = "_L__R__R_", target = "L______RR"

Output:

true

Explanation:

We can obtain the string target from start by doing the following moves:
- Move the first 'L' one step to the left → "L___R__R_"
- Move the last 'R' one step to the right → "L___R___R"
- Move the middle 'R' three steps to the right → "L______RR"

Example 2

Input:

start = "R_L_", target = "__LR"

Output:

false

Explanation:

The 'R' piece can move right to become "_RL_", but no further moves are possible to achieve "__LR".

Example 3

Input:

start = "_R", target = "R_"

Output:

false

Explanation:

The 'R' cannot move left to become "R_"; it can only move right.

Constraints

  • n == start.length == target.length
  • 1 <= n <= 10^5
  • start and target consist of the characters 'L', 'R', and '_'.

Approach and Intuition

To solve this, observe that:

  1. Filter by Piece Sequence: First, remove all '_' characters from both start and target. If the sequences of 'L' and 'R' pieces don't match, it's impossible to transform.

  2. Track Indices of Movable Pieces: Use two pointers to walk through the positions of 'L' and 'R' in both start and target. For each piece:

    • If the piece is 'L', it can only move left, so its position in start must be the position in target.
    • If the piece is 'R', it can only move right, so its position in start must be the position in target.
  3. Fail Fast: If any piece violates the above conditions, return false.

  4. Succeed if All Valid: If all pieces are matched correctly and in allowed directions, return true.

Complexity

  • Time Complexity: O(n) — Single pass for filtering and validation
  • Space Complexity: O(n) — For storing filtered positions of pieces

This efficient approach leverages constraints of movement and directional rules to validate transformations within the given bounds.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    bool canTransform(string start, string target) {
        int n = start.size();
        int i = 0, j = 0;

        while (i < n || j < n) {
            // Advance in start until non-'_' character
            while (i < n && start[i] == '_') {
                i++;
            }
            // Advance in target until non-'_' character
            while (j < n && target[j] == '_') {
                j++;
            }
            // Both indices should reach end simultaneously
            if (i == n || j == n) {
                return i == n && j == n;
            }
            // Verify characters and positions
            if (start[i] != target[j] ||
                (start[i] == 'L' && i < j) ||
                (start[i] == 'R' && i > j))
                return false;

            // Move to next character
            i++;
            j++;
        }

        return true;
    }
};

The C++ function canTransform within the Solution class determines if it's possible to rearrange the characters of the start string to match the target string by following specific movement rules for the characters 'L' and 'R'. The underscores '_' in the strings represent empty spaces where characters can move.

Here's an outline of how the function achieves this:

  • Size Check: First, it stores the size of the start string in variable n.

  • Simultaneous Iteration: Two indices i and j iterate over the start and target strings respectively, skipping over the underscores.

  • End Condition:

    • If one index reaches the end of its string before the other, it checks if both indices have simultaneously reached the end. If not, the function returns false indicating the strings can't be transformed into one another.
  • Character and Position Validation: The function then checks:

    • If the characters at the current indices of start and target differ, the transformation isn't possible.
    • If the character 'L' in the start wants to move right (if its index is less than j), or 'R' wants to move left (if its index is more than j), it violates the movement rules and thus, transformation isn't valid.
  • Index Increment: At the end of the loop, both indices i and j are incremented to move to the next characters in their respective strings.

  • Return Value: If all checks are passed, the function returns true.

The algorithm efficiently determines the possibility of transformation by using index manipulation and character comparisons, ensuring that every step adheres to the specified movement rules for 'L' and 'R'.

java
public class Solution {

    public boolean canTransform(String initial, String goal) {
        int len = initial.length();
        // Tracking indexes for both strings
        int indexInit = 0, indexGoal = 0;

        while (indexInit < len || indexGoal < len) {
            // Bypass the underscores in initial string
            while (
                indexInit < len && initial.charAt(indexInit) == '_'
            ) {
                indexInit++;
            }
            // Bypass the underscores in goal string
            while (
                indexGoal < len && goal.charAt(indexGoal) == '_'
            ) {
                indexGoal++;
            }
            // Verify both strings terminate at the same time
            if (indexInit == len || indexGoal == len) {
                return indexInit == len && indexGoal == len;
            }

            // Check characters and position rules
            if (
                initial.charAt(indexInit) != goal.charAt(indexGoal) ||
                (initial.charAt(indexInit) == 'L' && indexInit < indexGoal) ||
                (initial.charAt(indexInit) == 'R' && indexInit > indexGoal)
            ) return false;

            indexInit++;
            indexGoal++;
        }

        // All checks passed successfully
        return true;
    }
}

The Java function canTransform provides a method to determine whether you can transform the string initial into the string goal by moving the characters 'L' and 'R', with certain movement constraints, while ignoring the underscores ('_'). The function adheres to the idea that 'L' can only move left and 'R' can only move right in the string sequence.

Steps implemented in the code include:

  1. Initialize pointers to traverse through both initial and goal strings simultaneously.
  2. Use while loops to skip any underscores in both strings.
  3. Evaluate end conditions for both strings simultaneously — the traversal must exhaust both strings at the same point for the transformation to be valid.
  4. Compare corresponding characters of initial and goal after bypassing underscores:
    • Ensure characters match.
    • Confirm 'L' in initial is not to the right of its position in goal.
    • Confirm 'R' in initial is not to the left of its position in goal.
  5. Increment the pointers after each comparison.
  6. Conclude by returning true if all validations pass indicating that the transformation from initial to goal is possible following the given rules, otherwise return false.

Given these steps, the function efficiently checks for the possibility of transforming the initial string to the goal string by adhering to movement constraints of the specific characters, ensuring the discussed conditions are satisfied for each corresponding character in the two strings.

python
class Converter:
    def isConvertible(self, initial: str, final: str) -> bool:
        len_initial = len(initial)
        idx_initial, idx_final = 0, 0

        while idx_initial < len_initial or idx_final < len_initial:
            while idx_initial < len_initial and initial[idx_initial] == "_":
                idx_initial += 1
            while idx_final < len_initial and final[idx_final] == "_":
                idx_final += 1

            if idx_initial == len_initial or idx_final == len_initial:
                return idx_initial == len_initial and idx_final == len_initial

            if (
                initial[idx_initial] != final[idx_final]
                or (initial[idx_initial] == "L" and idx_initial < idx_final)
                or (initial[idx_initial] == "R" and idx_initial > idx_final)
            ):
                return False

            idx_initial += 1
            idx_final += 1

        return True

This Python3 solution defines a class Converter with a method isConvertible, which checks if one string can be transformed into another through specific reordering rules. The primary logic revolves around the manipulation and comparison of characters in two strings, initial and final.

  • Initial and final index pointers (idx_initial, idx_final) traverse both strings simultaneously, skipping over underscores ('_').
  • Validate if indices of both strings have reached the end simultaneously, ensuring both strings have the same format after ignoring underscores.
  • Confirm character equality at the current indices of both strings:
    • If characters are 'L' or 'R', validate their directional constraints:
      • 'L' must not move right (ensure idx_initial is not less than idx_final).
      • 'R' must not move left (ensure idx_initial is not greater than idx_final).
  • If any condition is violated, it returns False.
  • If all conditions are met throughout the loop, it finally returns True, indicating the final string is obtainable from the initial one through valid piece movements.

This approach efficiently uses linear time complexity, directly corresponding to the length of the strings, ensuring a quick validation process.

Comments

No comments yet.