#97 π§© 2337. Move Pieces to Obtain a String ππ§
Transforming one string into another through clever moves is a fascinating challenge. In this problem, we deal with moving characters L and R on a grid filled with blanks _ while adhering to strict movement rules. Can we turn the string start into target? Letβs find out! π
π Problem Statement
You are given two strings, start and target, each of length n. Both strings consist of the characters L, R, and _:
Lpieces can move left into an adjacent blank (_).Rpieces can move right into an adjacent blank (_)._represents a blank space, and it can be occupied by any piece (LorR).
Your task is to determine if it is possible to transform the string start into the string target by moving the pieces any number of times.
π Examples
Example 1:
Input:
start = "_L__R__R_"
target = "L______RR"
Output:
true
Explanation:
- Move the first
Lone step left:_L__R__R_βL___R__R_. - Move the last
Rone step right:L___R__R_βL___R___R. - Move the middle
Rthree steps right:L___R___RβL______RR.
We can achieve target, so we return true.
Example 2:
Input:
start = "R_L_"
target = "__LR"
Output:
false
Explanation:
- Move the
Rone step right:R_L_β_RL_. - The
Lcannot move right intoR, so we canβt matchtarget.
Example 3:
Input:
start = "_R"
target = "R_"
Output:
false
Explanation:
The R can only move to the right, so it cannot match the position in target.
π οΈ Constraints
n == start.length == target.length- (1 \leq n \leq 10^5)
startandtargetconsist only ofL,R, and_.
π‘ Key Observations
-
Matching Positions:
The relative order of the piecesLandRmust remain the same in both strings. We cannot βswapβ the positions of these characters during any moves. -
Blank Spaces (
_):
Blanks are flexible placeholders. They allow pieces to move but do not affect the order of pieces. - L and R Rules:
- An
Lcan only move left, so it cannot move right or end up to the right of its original position. - Similarly, an
Rcan only move right and cannot end up to the left of its original position.
- An
- Ignoring
_Positions:
Since_doesnβt determine the order ofLandR, we can filter them out from both strings when comparing.
β¨ Plan
To solve the problem efficiently and correctly, we need a structured plan that breaks down the requirements into logical steps. Hereβs an in-depth explanation of each step:
Step 1: Filter Relevant Characters
The strings start and target contain the characters L, R, and _. The _ represents blank spaces, which act as placeholders for movements but do not affect the order or identity of the pieces.
Our first task is to remove all _ characters from both strings, focusing only on the sequence of L and R pieces.
For example:
start = "_L__R__R_"β Filter βstart_pieces = ['L', 'R', 'R']target = "L______RR"β Filter βtarget_pieces = ['L', 'R', 'R']
If the two filtered sequences (start_pieces and target_pieces) are not identical in terms of characters and their order, it is impossible to transform start into target, and we can immediately return false.
Step 2: Record Character Positions
While the filtered sequences of characters (L and R) determine the order, their positions in the original strings determine whether the transformation is possible under the movement rules.
To retain the positional information, we pair each character with its index.
For example:
start = "_L__R__R_"βstart_positions = [('L', 1), ('R', 4), ('R', 7)]target = "L______RR"βtarget_positions = [('L', 0), ('R', 6), ('R', 7)]
Step 3: Validate Movement Rules
Next, we compare the corresponding characters and their positions in start_positions and target_positions. The movement rules are as follows:
- For
LPieces:Lcan only move left or stay in the same position.- If an
Lappears at a higher index instart_positionscompared totarget_positions, the transformation is invalid.
- For
RPieces:Rcan only move right or stay in the same position.- If an
Rappears at a lower index instart_positionscompared totarget_positions, the transformation is invalid.
For example:
- Start:
start_positions = [('L', 1), ('R', 4), ('R', 7)] - Target:
target_positions = [('L', 0), ('R', 6), ('R', 7)]'L', 1β'L', 0: β Valid, asLmoves left.'R', 4β'R', 6: β Valid, asRmoves right.'R', 7β'R', 7: β Valid, no movement required.
Step 4: Early Termination
To make the solution more efficient, we implement early termination checks:
- Mismatched Sequences: If the filtered sequences of
LandRare not identical betweenstartandtarget, returnfalseimmediately. - Invalid Movement: As we iterate over the positions, if any piece violates its movement rule (
Lmoves right orRmoves left), we can stop and returnfalse.
Step 5: Edge Cases
Before finalizing the implementation, consider these edge cases:
-
No Pieces (
LorR) in the Strings:
If bothstartandtargetconsist only of_, the result is alwaystruebecause no movement is needed. -
Unequal Length of Filtered Sequences:
If the count ofLandRpieces differs betweenstartandtarget, it is impossible to transform the strings. -
Single Character Scenarios:
Handle edge cases wherestartortargetcontains only oneLorR.
For example:start = "_L_",target = "L__"β Valid (L moves left).start = "_L_",target = "__L"β Invalid (L cannot move right).
Step 6: Iterate and Compare
After filtering and validating, iterate over the corresponding pairs of characters and their positions from start_positions and target_positions. Validate the movement of each character based on its rules (L left, R right). If all pairs satisfy the movement constraints, return true. Otherwise, return false.
This step-by-step approach ensures that we handle all scenarios while maintaining efficiency. By breaking the problem into smaller tasks, we simplify the logic and make the solution scalable for large inputs.
π§ Solution
Python Code
def canTransform(start: str, target: str) -> bool:
# Remove blanks to compare character order
start_pieces = [(char, i) for i, char in enumerate(start) if char != '_']
target_pieces = [(char, i) for i, char in enumerate(target) if char != '_']
# Step 1: Ensure the pieces match
if len(start_pieces) != len(target_pieces):
return False
for (start_char, start_pos), (target_char, target_pos) in zip(start_pieces, target_pieces):
# Pieces must have the same character and satisfy movement rules
if start_char != target_char:
return False
if start_char == 'L' and start_pos < target_pos:
return False # L can only move left
if start_char == 'R' and start_pos > target_pos:
return False # R can only move right
return True
β± Time Complexity
- Filtering Pieces: (O(n)), where (n) is the length of the string.
- Comparing Pieces: (O(n)) in the worst case when all characters are non-blanks.
Overall complexity: (O(n)).
Space complexity: (O(n)) for storing non-blank positions.
π οΈ Example Walkthrough
Letβs go step-by-step with the example:
Input:
start = "R__L__L_"
target = "__RLL___"
Step 1: Extract Pieces
start_pieces = [('R', 0), ('L', 3), ('L', 6)]target_pieces = [('R', 2), ('L', 3), ('L', 4)]
Step 2: Validate Character Order
- Both sequences contain
['R', 'L', 'L']. β
Step 3: Validate Movement Rules
('R', 0)β('R', 2): β (Right movement is allowed.)('L', 3)β('L', 3): β (No movement needed.)('L', 6)β('L', 4): β (Cannot moveLto the right.)
Output:
false
π§ Edge Cases
-
All Blanks:
start = "_____", target = "_____"
Output:true -
Empty Movements:
start = "L__R", target = "L__R"
Output:true -
Impossible Transformation:
start = "L_R", target = "R_L"
Output:false -
Mismatched Characters:
start = "L_R", target = "R_R"
Output:false
π Conclusion
This problem emphasizes character order and movement constraints. By filtering out blanks and verifying movement feasibility, we efficiently determine the transformationβs possibility. The linear complexity ensures scalability for larger inputs. Happy coding! π