1. 问题描述:
Dota2 的世界里有两个阵营:Radiant(天辉)和 Dire(夜魇)。Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参议员都可以行使两项权利中的一项:
禁止一名参议员的权利:
参议员可以让另一位参议员在这一轮和随后的几轮中丧失所有的权利。
宣布胜利:如果参议员发现有权利投票的参议员都是同一个阵营的,他可以宣布胜利并决定在游戏中的有关变化。给定一个字符串代表每个参议员的阵营。字母 “R” 和 “D” 分别代表了 Radiant(天辉)和 Dire(夜魇)。然后,如果有 n 个参议员,给定字符串的大小将是 n。以轮为基础的过程从给定顺序的第一个参议员开始到最后一个参议员结束。这一过程将持续到投票结束。所有失去权利的参议员将在过程中被跳过。假设每一位参议员都足够聪明,会为自己的政党做出最好的策略,你需要预测哪一方最终会宣布胜利并在 Dota2 游戏中决定改变。输出应该是 Radiant 或 Dire。
示例 1:
输入:"RD"
输出:"Radiant"
解释:第一个参议员来自 Radiant 阵营并且他可以使用第一项权利让第二个参议员失去权力,因此第二个参议员将被跳过因为他没有任何权利。然后在第二轮的时候,第一个参议员可以宣布胜利,因为他是唯一一个有投票权的人
示例 2:
输入:"RDD"
输出:"Dire"
解释:
第一轮中,第一个来自 Radiant 阵营的参议员可以使用第一项权利禁止第二个参议员的权利
第二个来自 Dire 阵营的参议员会被跳过因为他的权利被禁止
第三个来自 Dire 阵营的参议员可以使用他的第一项权利禁止第一个参议员的权利
因此在第二轮只剩下第三个参议员拥有投票的权利,于是他可以宣布胜利
提示:
给定字符串的长度在 [1, 10,000] 之间.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dota2-senate
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 思路分析:
分析题目可以知道主要有两个操作:① 当前党派的议员将另外一个党派的议员踢出局 ② 只剩下一个党派的议员那么当前党派宣布胜利,可以发现位置靠前的议员位置权力是比较大的,所以在踢对方出局的时候应该将位置靠前的对方议员踢出去,所以模拟整个过程即可。我们可以声明两个队列模拟这个过程,一开始的时候记录下每个党派议员的位置,当两个队列都不为空的时候执行整个过程,哪个党派的位置靠前那么当前党派就将对方位置最前面的那个议员踢出局,然后将当前行驶权力的议员的位置加入到队尾,并且我们需要在当前位置上加上n(n为senate的长度)这样表示下一轮模拟的时候位置是越来越大的,也即模拟新的一圈。
3. 代码如下:
import collections
class Solution:
# 其实是模拟整个过程
def predictPartyVictory(self, senate: str) -> str:
# 声明两个双端队列来存储各个党派出现的位置这样可以判断行驶权力的顺序
r, d = collections.deque(), collections.deque()
n = len(senate)
for i in range(len(senate)):
if senate[i] == "R":
r.append(i)
else:
d.append(i)
# 只有当两个队列都非空的时候执行这个过程
while r and d:
# 位置比对方靠前的议员将对方最靠前的议员踢出局, 并且当前议员需要加入到队尾, 加入到队尾的时候需要加上n表示接下来模拟新的一圈
if r[0] < d[0]:
r.append(r[0] + n)
else:
d.append(r[0] + n)
# 弹出队首元素
r.popleft()
d.popleft()
if len(r): return "Radiant"
return "Dire"