Dota2 Senate
Dota2 Senate is LeetCode 649 (Medium). The string senate lists senators in seat order: 'R' belongs to the Radiant party and 'D' to the Dire party. Senators speak one at a time in seat order, round after round, and a banned senator never speaks again. On their turn, a senator may:
- ban one senator of the other party, or
- announce victory, if every senator still in the game belongs to their own party.
Every senator plays the best strategy for their party. Return "Radiant" or "Dire", whichever party announces victory.
- n == senate.length
- 1 <= n <= 10⁴
- senate[i] is either 'R' or 'D'.
Intuition
On your turn, one opponent will speak before all the others: the first opponent after you in speaking order, counting into the next round if needed. That opponent is the one who can hurt your party soonest, so ban them. Banning a later opponent leaves the nearer one free to ban one of your senators first, and gains nothing in exchange.
With every move fixed, the game is a simulation. Give each senator a turn number, starting with their seat. Of the two parties' next speakers, the smaller turn number speaks first and bans the other. The speaker then takes a new turn number in the next round.
Players who act in a fixed cycle and drop out one by one point to a queue: the front is whoever acts next, and anyone who survives goes to the back. Two competing sides means two queues, compared front to front.
Approach
Before reading on: play "DDRRR" by hand, with every senator banning the next opponent due to speak. Who wins, and why does having more seats not help? Then decide what number a surviving senator should carry into the next round so that a single comparison still finds the next speaker. Aim for O(n).
Split the seats into two queues
Put the seat numbers of the 'R' senators in one queue and those of the 'D' senators in another, in seat order. The front of each queue is the next senator from that party to speak.
Let the earlier front ban the other
Pop both fronts. The smaller turn number speaks first, and the other front is exactly the opponent due to speak soonest, so that senator is banned. A banned senator is simply never pushed back.
Send the speaker to the next round
Push the speaker back onto its own queue with turn number + n. That places it after everyone still waiting in the current round, and senators who rejoin keep the same order they spoke in.
Stop when one queue is empty
Loop while both queues have senators. When one empties, every senator left belongs to the other party, and its next speaker announces victory, so return that party's name.
Dota2 Senate solution in Python | C++ | Java
Common pitfalls
Picking the party with more senators
if senate.count("R") >= senate.count("D"):
return "Radiant"
return "Dire"while radiant and dire:
...
return "Radiant" if radiant else "Dire"Speaking order matters more than numbers. In "DDRRR", both Dire senators speak first and ban two of the three Radiant senators before any of them speaks. The last Radiant senator bans one Dire senator, the other Dire senator bans it, and Dire wins.
Rejoining with the same turn number
if r < d:
radiant.append(r)if r < d:
radiant.append(r + n)In "RDD", seat 0 bans seat 1 and rejoins as turn 0 instead of 3. Turn 0 still looks earlier than seat 2, so seat 0 speaks twice in one round and the code returns "Radiant". In the real game seat 2 speaks next, bans seat 0, and Dire wins.
Edge cases
"RRR"The Dire queue starts empty, so the loop never runs and the first Radiant senator announces victory: "Radiant".
Complexity
Dota2 Senate FAQ
Can the turn numbers overflow?
No. Each pass bans one senator, so a senator can rejoin at most n − 1 times, and every rejoin adds n. No turn number reaches n², which for n = 10⁴ is 10⁸, well inside a 32-bit integer.
Is there a way to solve it without two queues?
Yes. Walk the senate as one growing list and keep a running count of bans waiting to land on each party. A senator who is owed a ban is skipped; any other senator adds a pending ban against the other party and is appended to the end for the next round. It is also O(n), but the two queues make the speaking order easier to follow.