力扣649-Dota2 参议院
一、原题题目
1.1 题目
Dota2 的世界里有两个阵营:Radiant (天辉)和 Dire(夜魇)。Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参议员都可以行使两项权利中的一项:
禁止一名参议员的权利:参议员可以让另一位参议员在这一轮和随后的几轮中丧失所有的权利。
宣布胜利:如果参议员发现有权利投票的参议员都是同一个阵营的,他可以宣布胜利并决定在游戏中的有关变化。
给定一个字符串代表每个参议员的阵营。字母 “R” 和 “D” 分别代表了 Radiant(天辉)和 Dire(夜魇)。然后,如果有 n 个参议员,给定字符串的大小将是 n。以轮为基础的过程从给定顺序的第一个参议员开始到最后一个参议员结束。这一过程将持续到投票结束。所有失去权利的参议员将在过程中被跳过。假设每一位参议员都足够聪明,会为自己的政党做出最好的策略,你需要预测哪一方最终会宣布胜利并在 Dota2 游戏中决定改变。输出应该是 Radiant 或 Dire。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dota2-senate
1.2 示例
示例1:
输入:“RD”
输出:“Radiant”
解释:第一个参议员来自 Radiant 阵营并且他可以使用第一项权利让第二个参议员失去权力,因此第二个参议员将被跳过因为他没有任何权利。然后在第二轮的时候,第一个参议员可以宣布胜利,因为他是唯一一个有投票权的人。示例2:
输入:“RDD”
输出:“Dire”
解释:
第一轮中,第一个来自 Radiant 阵营的参议员可以使用第一项权利禁止第二个参议员的权利,第二个来自 Dire 阵营的参议员会被跳过因为他的权利被禁止,第三个来自 Dire 阵营的参议员可以使用他的第一项权利禁止第一个参议员的权利,因此在第二轮只剩下第三个参议员拥有投票的权利,于是他可以宣布胜利。提示:
给定字符串的长度在
[1, 10,000]
之间.
二、解题思路
2.1 题目意思理解
如果读明白了题目的意思,应该可以理解当前参议员要么是被前面的另一队参议员禁止了,否则就应该去禁止后面最靠近它的另一队参议员。
可以理解为带攻击属性的一种游戏。先定义下我们的游戏。
游戏有两个队,D队和R队,目标是杀光其他队的所有人,即可获得胜利✌️。战士是一个一个到达战场的。
Dnumber 和 Rnumber 分别表示两个队的总人数,可以通过一次遍历输入数据获得。
Dattack 和 Rattack 分别表示两个队当前的攻击力属性,为几就表示可以杀死对方几个人。
Ddie 和 Rdie 分别表示两个队当前死了多少英雄战士,当死亡人数等于总人数时,对方获胜。
第一次遍历输入数据
需要统计每个对的总人数并进行一轮厮杀。被杀死的战士将其原大写字母改为小写字母记入史册,永垂不朽。
后几轮遍历就是完全厮杀
直到出现哪个对死亡人数达到总队伍人数,对方队获胜。
三、代码实现
3.1 详细代码(Java)
public class Solution {
public String predictPartyVictory(String senate) {
int Rnumber = 0, Dnumber = 0; // 记录每个队的总人数
int Rattack = 0, Dattack = 0; // 记录每个队的攻击值
int Rdie = 0, Ddie = 0; // 记录每个对的死亡战士
char[] chars = senate.toCharArray(); // 将字符串转换成字符数组方便遍历处理
// 第一轮统计总人数并厮杀一轮
for (int i = 0; i < chars.length; i++) {
if (chars[i] == 'D') { // 来的是D队战士
Dnumber++; // D队人数加1
if (Rattack > 0) { // 如果R队攻击值大于0
chars[i] = 'd'; // 则刚刚上来的D队战士成炮灰
Rattack--; // 同时消耗R队一个攻击值
Ddie++; // D队死亡人数加1
} else Dattack++; // 如果R队攻击值为0,则D队攻击值积累加1
} else { // 来的是R队战士
Rnumber++; // R队人数加1
if (Dattack > 0) { // 如果D队攻击值大于0
chars[i] = 'r'; // 则刚刚上来的R队战士成炮灰
Dattack--; // 同时消耗D队一个攻击值
Rdie++; // R队死亡人数加1
} else Rattack++; // 如果D队攻击值为0,则R队攻击值积累加1
}
}
// 后几轮厮杀
for (int i = 0; i <= chars.length; i++) {
if (i == chars.length) { // 这个 if 判断达到轮战的目的
i = -1;
continue;
}
// 战士战死,直接跳过,先判断这个可以提高性能
if (chars[i]=='d'||chars[i]=='r') continue;
if(Rdie==Rnumber) return "Dire"; // R队被歼灭,D队获胜
if(Ddie==Dnumber) return "Radiant"; // D队被歼灭,R队获胜
if (chars[i] == 'D') { // 来的是D队战士,不加总人数其他同上处理
if (Rattack > 0) {
Rattack--;
chars[i] = 'd';
Ddie++;
if (Ddie == Dnumber) return "Radiant"; // 判断是否结束
} else Dattack++;
} else { // 来的是R队战士,不加总人数其他同上处理
if (Dattack > 0) {
Dattack--;
chars[i] = 'r';
Rdie++;
if (Rdie == Rnumber) return "Dire"; // 判断是否结束
} else Rattack++;
}
}
return ""; // 因为上面的return语句都在if语句后,所以加上这个不会被执行的return语句
}
}
3.2 算法执行结果

四、总结分析
个人感觉这个题目是题目意思有点让人费解,读懂题目意思后思路还是挺简单的。