Bag of Tokens
Medium · Two Pointers · Explanation and code example
Greedy + Two Pointers
How it works
To maximize our score, we should be strategic about which tokens we play face-up (losing power, gaining score) versus face-down (gaining power, losing score). The key insight is that when gaining score, we want to spend as little power as possible, and when gaining power, we want to gain as much as possible. Sorting the tokens lets us always play the smallest token face-up and the largest token face-down.
Steps
- Sort the tokens in ascending order.
- Use two pointers:
lstarts at the beginning,rat the end. - While
l <= r:- If we have enough power to play
tokens[l]face-up, do it (gain1score, lose that power). Update the maximum score seen. - Else if we have at least
1score, playtokens[r]face-down (lose1score, gain that power). - Otherwise, we can't make any more moves, so break.
- If we have enough power to play
- Return the maximum score achieved.
Complexity
- Time complexity:
O(n log n) - Space complexity:
O(1)orO(n)depending on the sorting algorithm.
Things to watch for
Forgetting to Sort the Tokens
The greedy approach only works on sorted tokens. Without sorting, you cannot guarantee playing the smallest token face-up and largest face-down.
Playing Face-Down with Zero Score
You cannot play a token face-down to gain power unless you have at least 1 score to spend. Attempting this leads to incorrect results.
Returning Current Score Instead of Maximum
The score fluctuates as you play tokens face-down. You must track the maximum score achieved, not just the final score.
Python code example
from typing import List
class Solution:
def bagOfTokensScore(self, tokens: List[int], power: int) -> int:
res = score = 0
tokens.sort()
l, r = 0, len(tokens) - 1
while l <= r:
if power >= tokens[l]:
power -= tokens[l]
l += 1
score += 1
res = max(res, score)
elif score > 0:
power += tokens[r]
r -= 1
score -= 1
else:
break
return res
C++ code example
class Solution {
public:
int bagOfTokensScore(vector<int>& tokens, int power) {
sort(tokens.begin(), tokens.end());
int res = 0, score = 0, l = 0, r = tokens.size() - 1;
while (l <= r) {
if (power >= tokens[l]) {
power -= tokens[l++];
score++;
res = max(res, score);
} else if (score > 0) {
power += tokens[r--];
score--;
} else {
break;
}
}
return res;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.