「leetcode」649.Dota2 参议院

原题

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] 之间.

思路

在每一轮议会选举时,天灾和近卫的优先策略是禁止临近的对方参议员的权利。

我们循环所有参议员,并把双方对应的索引,存储到不同的数组中。

我们依次比较两个数组中,每一位对应的索引。如果天灾的索引小于近卫的索引,那么会淘汰一名近卫的参议院,反之同理。

如果天灾和近卫的人数不相等。如果天灾的人数大于近卫,我们会从前淘汰近卫的参议院。反之同理。

当第一次议会循环结束时,我们重置索引为0,然后重复上述的过程。当有一方人数为0的时候,就可以判断谁获得了议会的选举。

本题也是贪心算法的一种,我们优先做出对局部最优的策略,优先淘汰对方的参议院。减少对方参议院的数量。

代码


/**
 * @param {string} senate
 * @return {string}
 */
var predictPartyVictory = function(senate) {
    let radiants = []
    let dires = []
    
    let radiantIndex = 0
    let direIndex = 0
    
    for (let i = 0; i < senate.length; i++) {
        if (senate[i] === 'R') {
            radiants.push(i)
        } else {
            dires.push(i)
        }
    }
    
    while (radiants.length && dires.length) {
        
        // 一次循环结束
        if (
            radiants[radiantIndex] === undefined &&
            dires[direIndex] === undefined
        ) {
            radiantIndex = 0
            direIndex = 0
        }
        
        // 如果本次循环中radiants已经结束
        if (
            radiants[radiantIndex] === undefined &&
            dires[direIndex] !== undefined
        ) {
            direIndex += 1
            radiants.shift()
            continue
        }
        
        // 如果本次循环中dires已经结束
        if (
            radiants[radiantIndex] !== undefined &&
            dires[direIndex] === undefined
        ) {
            radiantIndex += 1
            dires.shift()
            continue
        }
        
        // 
        if (dires[direIndex] > radiants[radiantIndex]) {
            radiantIndex += 1
            dires.splice(direIndex, 1)
        } else {
            direIndex += 1
            radiants.splice(radiantIndex, 1)
        }
    }
    
    return radiants.length ? 'Radiant' : 'Dire'
};

你可能感兴趣的:(算法,javascript)