class Leaderboard:
def __init__(self):
self.scores = defaultdict()
def addScore(self, playerId: int, score: int) -> None:
if playerId not in self.scores:
self.scores[playerId] = 0
self.scores[playerId] += score
def top(self, K: int) -> int:
values = [v for _, v in sorted(self.scores.items(), key=lambda item: item[1])]
values.sort(reverse=True)
total, i = 0, 0
while i < K:
total += values[i]
i += 1
return total
def reset(self, playerId: int) -> None:
self.scores[playerId] = 0Time complexity:
addScoreresettopSpace complexity:
Where is the total number of players in the leaderboard.
class Leaderboard:
def __init__(self):
self.scores = {}
def addScore(self, playerId: int, score: int) -> None:
if playerId not in self.scores:
self.scores[playerId] = 0
self.scores[playerId] += score
def top(self, K: int) -> int:
# This is a min-heap by default in Python.
heap = []
for x in self.scores.values():
heapq.heappush(heap, x)
if len(heap) > K:
heapq.heappop(heap)
res = 0
while heap:
res += heapq.heappop(heap)
return res
def reset(self, playerId: int) -> None:
self.scores[playerId] = 0Time complexity:
addScoreresettopSpace complexity:
Where is the total number of players in the leaderboard, and is the number of top-scoring players.
from sortedcontainers import SortedDict
class Leaderboard:
def __init__(self):
self.scores = {}
self.sortedScores = SortedDict()
def addScore(self, playerId: int, score: int) -> None:
# The scores dictionary simply contains the mapping from the
# playerId to their score. The sortedScores contain a BST with
# key as the score and value as the number of players that have
# that score.
if playerId not in self.scores:
self.scores[playerId] = score
self.sortedScores[-score] = self.sortedScores.get(-score, 0) + 1
else:
preScore = self.scores[playerId]
val = self.sortedScores.get(-preScore)
if val == 1:
del self.sortedScores[-preScore]
else:
self.sortedScores[-preScore] = val - 1
newScore = preScore + score
self.scores[playerId] = newScore
self.sortedScores[-newScore] = self.sortedScores.get(-newScore, 0) + 1
def top(self, K: int) -> int:
count, total = 0, 0
for key, value in self.sortedScores.items():
times = self.sortedScores.get(key)
for _ in range(times):
total += -key
count += 1
# Found top-K scores, break.
if count == K:
break
# Found top-K scores, break.
if count == K:
break
return total
def reset(self, playerId: int) -> None:
preScore = self.scores[playerId]
if self.sortedScores[-preScore] == 1:
del self.sortedScores[-preScore]
else:
self.sortedScores[-preScore] -= 1
del self.scores[playerId]Time complexity:
for addScore
for reset. Note that this complexity is in the case when every player always maintains a unique score.
for top. Note that if the data structure doesn't provide a natural iterator, then we can simply get a list of all the key-value pairs and they will naturally be sorted due to the nature of this data structure. In that case, the complexity would be since we would be forming a new list.
Space complexity: used by the scores dictionary. Also, if you obtain all the key-value pairs in a new list in the top function, then an additional would be used.
Where is the total number of players in the leaderboard, and is the number of top-scoring players.