2038. Remove Colored Pieces if Both Neighbors are the Same Color - Explanation
Description
Alice and Bob alternate turns removing pieces from the string colors, with Alice moving first. Alice may remove an A only when its immediate neighbors are both A. Bob may remove a B only when its immediate neighbors are both B. End pieces cannot be removed. The remaining pieces close the gap after a removal.
A player who has no legal move loses. Assuming optimal play, return true if Alice wins and false if Bob wins.
Example 1:
Input: colors = "AAA"
Output: trueExplanation: Alice removes the middle A, leaving AA. Bob has no legal move, so Alice wins.
Example 2:
Input: colors = "AAABBB"
Output: falseExplanation: Alice must remove the middle A, leaving AABBB. Bob removes the middle B, leaving AABB. Alice then has no move and loses.
Example 3:
Input: colors = "AAAABBB"
Output: trueExplanation: Alice can remove two pieces from the initial run of four As, while Bob can remove only one B. After Alice, Bob, and Alice move, Bob has no legal move.
Constraints:
1 <= colors.length <= 100000- Only
AandBoccur.
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- String Manipulation - Iterating through strings and checking character patterns
- Two Pointers - Using pointers to track consecutive runs of characters
- Greedy Algorithms - Making locally optimal choices to find the global optimum
- Game Theory Basics - Understanding turn-based games and win conditions
1. Brute Force
Intuition
We simulate the game turn by turn. Alice looks for a piece 'A' surrounded by two other 'A's and removes it. Then Bob does the same for 'B'. If a player cannot make a move on their turn, they lose. This straightforward simulation mirrors the actual gameplay but is slow because we repeatedly scan and modify the string.
Algorithm
- Convert the string to a mutable list.
- Alternate turns between Alice (
'A') and Bob ('B'). - On each turn, scan for a removable piece (one that has the same color on both sides).
- If found, remove it and continue. If not found, the current player loses.
- Alice wins if Bob cannot move; Bob wins if Alice cannot move.
class Solution:
def winnerOfGame(self, colors: str) -> bool:
s = list(colors)
def removeChar(c):
for i in range(1, len(s) - 1):
if s[i] != c:
continue
if s[i] == s[i + 1] == s[i - 1]:
s.pop(i)
return True
return False
while True:
if not removeChar('A'):
return False
if not removeChar('B'):
return True
return FalseTime & Space Complexity
- Time complexity:
- Space complexity:
2. Greedy + Two Pointers
Intuition
The key insight is that each player's moves are independent. Removing an 'A' from a sequence of A's doesn't affect Bob's sequences of B's, and vice versa. So instead of simulating the game, we can count how many moves each player has available. For a run of consecutive same-colored pieces of length k, a player can remove k - 2 pieces (since they need neighbors on both sides). Alice wins if she has more moves than Bob.
Algorithm
- Use two pointers to track consecutive runs of the same color.
- For each position, calculate how many "extra" pieces exist beyond the first two in the current run.
- Add these extras to Alice's count if the color is
'A', or Bob's count if'B'. - Return
trueif Alice has more moves than Bob.
Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
3. Greedy
Intuition
This is a cleaner way to count available moves. For each position in the middle of the string, we check if it forms a "triplet" of same-colored pieces. Each such triplet represents one potential move for that player. Since removing a piece from a longer run still leaves valid triplets, we simply count all triplet centers for each player.
Algorithm
- Initialize counters for Alice and Bob.
- Iterate through positions
1ton-2(excluding endpoints). - At each position, check if the current piece matches both its neighbors.
- If so, increment Alice's counter for
'A'or Bob's counter for'B'. - Return
trueif Alice's count exceeds Bob's count.
Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
Common Pitfalls
Simulating the Game Turn by Turn
A common mistake is to simulate the actual game by removing pieces one at a time and alternating turns. This leads to O(n^2) time complexity because each removal requires scanning and modifying the string. The key insight is that removing an 'A' from a sequence of A's doesn't affect Bob's available moves on B sequences, and vice versa. Instead of simulating, simply count the available moves for each player upfront.
Miscounting Available Moves
When counting moves, remember that a player can only remove a piece if it has neighbors of the same color on both sides. For a run of k consecutive same-colored pieces, the number of removable pieces is k - 2 (not k or k - 1). A run of length 1 or 2 gives zero moves. Some solutions incorrectly count individual pieces or forget to subtract 2 for the boundary pieces that cannot be removed.
Using the Wrong Win Condition
The problem asks if Alice wins, and Alice moves first. Some solutions return alice >= bob instead of alice > bob. Since Alice needs strictly more moves than Bob to win (she goes first, so if they have equal moves, Bob makes the last move and Alice loses), the correct condition is alice > bob.
Sign in to join the discussion