一、题目
Dota2 的世界里有两个阵营:Radiant
(天辉)和 Dire
(夜魇)
Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参议员都可以行使两项权利中的 一 项:
- 禁止一名参议员的权利:参议员可以让另一位参议员在这一轮和随后的几轮中丧失 所有的权利 。
- 宣布胜利:如果参议员发现有权利投票的参议员都是 同一个阵营的 ,他可以宣布胜利并决定在游戏中的有关变化。
给你一个字符串 senate
代表每个参议员的阵营。字母 'R'
和 'D'
分别代表了 Radiant
(天辉)和 Dire
(夜魇)。然后,如果有 n
个参议员,给定字符串的大小将是 n
。
以轮为基础的过程从给定顺序的第一个参议员开始到最后一个参议员结束。这一过程将持续到投票结束。所有失去权利的参议员将在过程中被跳过。
假设每一位参议员都足够聪明,会为自己的政党做出最好的策略,你需要预测哪一方最终会宣布胜利并在 Dota2 游戏中决定改变。输出应该是 "Radiant"
或 "Dire"
。
示例 1:
输入:senate = "RD" 输出:"Radiant" 解释: 第 1 轮时,第一个参议员来自 Radiant 阵营,他可以使用第一项权利让第二个参议员失去所有权利。这一轮中,第二个参议员将会被跳过,因为他的权利被禁止了。第 2 轮时,第一个参议员可以宣布胜利,因为他是唯一一个有投票权的人。
示例 2:
输入:senate = "RDD" 输出:"Dire" 解释: 第 1 轮时,第一个来自 Radiant 阵营的参议员可以使用第一项权利禁止第二个参议员的权利。 这一轮中,第二个来自 Dire 阵营的参议员会将被跳过,因为他的权利被禁止了。 这一轮中,第三个来自 Dire 阵营的参议员可以使用他的第一项权利禁止第一个参议员的权利。 因此在第二轮只剩下第三个参议员拥有投票的权利,于是他可以宣布胜利
提示:
n == senate.length
1 <= n <= 10^4
senate[i]
为'R'
或'D'
二、解题思路
这个问题可以通过贪心算法和循环队列来解决。每个参议员都会优先禁止下一个敌对阵营的参议员的权利,以确保自己阵营的参议员能够存活到下一轮。我们可以使用两个队列分别存储 Radiant 和 Dire 阵营的参议员的索引,然后模拟投票过程。
核心思路
2.1 初始化队列:
使用两个队列 radiantQueue 和 direQueue 分别存储 Radiant 和 Dire 阵营的参议员的索引。
2.2 模拟投票过程:
每次从队列中取出一个参议员,检查其阵营。
如果当前参议员是 Radiant,则禁止下一个 Dire 参议员的权利(从 direQueue 中移除)。
如果当前参议员是 Dire,则禁止下一个 Radiant 参议员的权利(从 radiantQueue 中移除)。
将当前参议员的索引加上 n(表示进入下一轮)并重新加入队列。
2.3 终止条件:
当其中一个队列为空时,表示该阵营的参议员全部被禁止,另一个阵营获胜。
三、代码实现
#include <iostream>
#include <queue>
#include <string>
using namespace std;
string predictPartyVictory(string senate) {
int n = senate.size();
queue<int> radiantQueue, direQueue;
// 初始化队列
for (int i = 0; i < n; ++i) {
if (senate[i] == 'R') {
radiantQueue.push(i);
} else {
direQueue.push(i);
}
}
// 模拟投票过程
while (!radiantQueue.empty() && !direQueue.empty()) {
int rIndex = radiantQueue.front();
int dIndex = direQueue.front();
radiantQueue.pop();
direQueue.pop();
// 当前参议员禁止下一个敌对阵营的参议员
if (rIndex < dIndex) {
radiantQueue.push(rIndex + n); // 进入下一轮
} else {
direQueue.push(dIndex + n); // 进入下一轮
}
}
// 返回获胜阵营
return radiantQueue.empty() ? "Dire" : "Radiant";
}
int main() {
// 示例 1
string senate1 = "RD";
cout << "示例 1 结果: " << predictPartyVictory(senate1) << endl;
return 0;
}
时间复杂度:O(n),每个参议员最多被处理一次。
空间复杂度:O(n),用于存储队列。
通过贪心算法和循环队列的结合,我们可以高效地模拟参议员的投票过程,并确定最终的获胜阵营。这种方法的时间复杂度和空间复杂度均为 O(n),适用于大规模输入。