Before attempting this problem, you should be comfortable with:
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.
l starts at the beginning, r at the end.l <= r:tokens[l] face-up, do it (gain 1 score, lose that power). Update the maximum score seen.1 score, play tokens[r] face-down (lose 1 score, gain that power).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 resThe greedy approach only works on sorted tokens. Without sorting, you cannot guarantee playing the smallest token face-up and largest face-down.
# Wrong: using unsorted tokens
l, r = 0, len(tokens) - 1
# Right: sort first
tokens.sort()
l, r = 0, len(tokens) - 1You cannot play a token face-down to gain power unless you have at least 1 score to spend. Attempting this leads to incorrect results.
# Wrong: no score check before face-down play
else:
power += tokens[r]
r -= 1
score -= 1
# Right: require score > 0
elif score > 0:
power += tokens[r]
r -= 1
score -= 1The score fluctuates as you play tokens face-down. You must track the maximum score achieved, not just the final score.
# Wrong: returning final score
return score
# Right: track and return maximum
res = max(res, score) # update after each face-up play
return res