Skip to content
BASA DSA

Design a Balanced Server Manager

MediumArrays & Hashing

Custom BASA DSA problem, based on your server-session scenario.

Implement a Python ServerManager that distributes persistent sessions across servers. Sessions stay active until explicitly removed. Every active session must exist on exactly one server.

  • ServerManager(n) creates n empty servers named n1, n2, ..., nN in numeric order.

  • addSession(sessionId) adds a new string ID to a server with the fewest sessions and returns that server's name. Break ties by numeric server order (n2 comes before n10). If the ID is already active, return its current server without changing anything.

  • removeSession(sessionId) removes that session and returns True, or False if it is absent. After a successful removal, rebalance immediately using the rule below.

  • getServerCounts() returns a fresh dictionary mapping every server name to its session count, including zero counts. Reading must not change state, and later operations must not change an earlier snapshot.

Balance invariant: after every completed operation, the largest and smallest server counts differ by at most one. Rebalancing may move an existing session to another server; never drop or duplicate a session.

Deterministic removal rule: after removing the ID, find the least-loaded and most-loaded servers, breaking both ties by numeric server order. If their counts differ by more than one, move the earliest-arriving session on the most-loaded server to the least-loaded server. A moved session becomes the latest arrival on its destination. Duplicate additions do not change arrival order. Otherwise, move nothing. Follow this rule so everyone gets the same observable answers.

Calls happen sequentially. You are modeling the manager in memory; no networking or concurrency is required. You may use Python's standard library. TypeScript is also available.

In the examples and custom inputs, the first array lists operations and the second array lists their arguments. The constructor produces null in the output; Python True and False appear as JSON true and false.

Your requested scenario: initialize with 3, then add the string IDs "1" through "100". The final counts are {"n1": 34, "n2": 33, "n3": 33}. Balance must also hold after any subsequent removals.

Example 1 · Add sessions

Input
arg 1 = ["ServerManager","getServerCounts","addSession","addSession","addSession","addSession","getServerCounts"]
arg 2 = [[3],[],["1"],["2"],["3"],["4"],[]]
Output
[null,{"n1":0,"n2":0,"n3":0},"n1","n2","n3","n1",{"n1":2,"n2":1,"n3":1}]

Explanation

All servers start at zero. The first three sessions go to n1, n2, and n3. All three then have one session, so session "4" goes to n1 by numeric server order. The counts are n1: 2, n2: 1, n3: 1.

Example 2 · Rebalance after removal

Input
arg 1 = ["ServerManager","addSession","addSession","addSession","addSession","getServerCounts","removeSession","getServerCounts","addSession","removeSession","getServerCounts"]
arg 2 = [[3],["1"],["2"],["3"],["4"],[],["2"],[],["1"],["missing"],[]]
Output
[null,"n1","n2","n3","n1",{"n1":2,"n2":1,"n3":1},true,{"n1":1,"n2":1,"n3":1},"n2",false,{"n1":1,"n2":1,"n3":1}]

Explanation

Before removal, n1 holds ["1", "4"], n2 holds ["2"], and n3 holds ["3"]. Removing "2" creates counts 2, 0, 1. Move "1", the earliest arrival on n1, to n2. All counts become 1. Adding existing session "1" returns its current server n2 without adding a copy. Removing a missing session returns false.

Example 3 · Three servers, 100 sessions

Input
arg 1 = ["ServerManager","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","addSession","getServerCounts"]
arg 2 = [[3],["1"],["2"],["3"],["4"],["5"],["6"],["7"],["8"],["9"],["10"],["11"],["12"],["13"],["14"],["15"],["16"],["17"],["18"],["19"],["20"],["21"],["22"],["23"],["24"],["25"],["26"],["27"],["28"],["29"],["30"],["31"],["32"],["33"],["34"],["35"],["36"],["37"],["38"],["39"],["40"],["41"],["42"],["43"],["44"],["45"],["46"],["47"],["48"],["49"],["50"],["51"],["52"],["53"],["54"],["55"],["56"],["57"],["58"],["59"],["60"],["61"],["62"],["63"],["64"],["65"],["66"],["67"],["68"],["69"],["70"],["71"],["72"],["73"],["74"],["75"],["76"],["77"],["78"],["79"],["80"],["81"],["82"],["83"],["84"],["85"],["86"],["87"],["88"],["89"],["90"],["91"],["92"],["93"],["94"],["95"],["96"],["97"],["98"],["99"],["100"],[]]
Output
[null,"n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1","n2","n3","n1",{"n1":34,"n2":33,"n3":33}]

Explanation

Add session IDs "1" through "100", in that order. Every group of three additions increases each server count by one. After 99 additions the counts are 33, 33, 33; session "100" goes to n1. The final snapshot is {"n1": 34, "n2": 33, "n3": 33}.

Constraints

  • 1 <= n <= 100.
  • 1 <= sessionId length <= 64 characters; IDs are opaque, case-sensitive strings.
  • At most 2,000 operations per test case, including construction and reads.
  • An ID can be added again after removal; at most 1,000 sessions are active at once.
  • Every test begins with ServerManager(n). All subsequent operations use the exact method names shown above.

Class contractServerManagerArguments: json, json
Loading draft…
SolutionRuns on your device
Loading draft…