codejump
MediumPythonJavaScriptTypeScript

System Design — Game Leaderboard

System DesignSortingHash Map

Scores go up and down, and the product needs "top K" and "my rank" at any time.

solve(args, ops) builds new Leaderboard() and replays ops:

  • add(player, delta) — add delta (may be negative) to the player's score; an unknown

player starts at 0. Returns the player's new score.

  • top(k) — return the ids of the k best players, best first. Fewer players than k is fine.
  • rank(player) — the 1-based position of the player, or -1 for an unknown player.
  • reset(player) — remove the player from the board. Returns nothing.

Ordering is pinned: higher score first; on equal scores the smaller player id (plain
string comparison) comes first. Players with equal scores therefore do *not* share a rank.

A sort on every query is acceptable here. In production you would keep a sorted structure
(balanced tree, skip list or Redis sorted set) so top and rank are O(log n) — be ready to
say so.

Example

add("a",10) add("b",20) add("c",20)  top(2) → ["b","c"]   rank("a") → 3

Sample tests

Test #1Ties broken by id, resets and re-ranking
Input: [[],[["add","a",10],["add","b",20],["add","c",20],["top",2],["rank","a"],["add","a",15],["top",1],["rank","b"],["reset","a"],["rank","a"],["top",5]]]
Output: [10,20,20,["b","c"],3,25,["a"],2,null,-1,["b","c"]]
Test #2Empty leaderboard
Input: [[],[["top",3],["rank","ghost"]]]
Output: [[],-1]
Test #3Negative scores
Input: [[],[["add","x",5],["add","x",-8],["add","y",-1],["top",2],["rank","x"]]]
Output: [5,-3,-1,["y","x"],2]