Dota2 Senate
Medium · Greedy · Explanation and code example
Greedy
How it works
We can track pending bans using a single counter. When we encounter a Radiant senator (R), they either get banned by a waiting Dire (if cnt < 0) or they ban a future Dire senator. Similarly, Dire senators either get banned or ban future Radiant senators. The twist is that when a senator is banned, their surviving opponent is appended to the end to act again in future rounds.
Steps
- Convert the string to a list and initialize a counter
cnt = 0. - Iterate through the list (which grows as we append survivors):
- If the senator is
R:- If
cnt < 0, a Dire senator bans them; appendDto the end. - Increment
cnt(representing a pending Radiant action).
- If
- If the senator is
D:- If
cnt > 0, a Radiant senator bans them; appendRto the end. - Decrement
cnt(representing a pending Dire action).
- If
- If the senator is
- After processing, if
cnt > 0, Radiant wins; otherwise, Dire wins.
Complexity
- Time complexity:
O(n) - Space complexity:
O(n)
Things to watch for
Not Understanding the Circular Nature
The senate voting is circular, meaning after the last senator votes, it wraps back to the first. A banned senator in round 1 could have banned someone who would act later in the same round or in subsequent rounds.
Banning the Wrong Opponent
Each senator should optimally ban the nearest opposing senator who would otherwise act before them in the next round. Banning a distant opponent wastes the opportunity and may lead to suboptimal outcomes.
Forgetting to Re-add Surviving Senators
In the queue-based approach, when a senator bans an opponent, the survivor must be re-added to the queue to vote again in future rounds. The index must be incremented by n to maintain proper ordering.
Python code example
class Solution:
def predictPartyVictory(self, senate: str) -> str:
senate = list(senate)
cnt = i = 0
while i < len(senate):
c = senate[i]
if c == 'R':
if cnt < 0:
senate.append('D')
cnt += 1
else:
if cnt > 0:
senate.append('R')
cnt -= 1
i += 1
return "Radiant" if cnt > 0 else "Dire"
C++ code example
class Solution {
public:
string predictPartyVictory(string senate) {
int cnt = 0, i = 0;
while (i < senate.size()) {
char c = senate[i];
if (c == 'R') {
if (cnt < 0) {
senate.push_back('D');
}
cnt++;
} else {
if (cnt > 0) {
senate.push_back('R');
}
cnt--;
}
i++;
}
return cnt > 0 ? "Radiant" : "Dire";
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.