1. 程式人生 > 其它 >Leetcode: NO.649 Dota2 參議院 貪心演算法

Leetcode: NO.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] 之間.

連結:https://leetcode-cn.com/problems/dota2-senate

解題記錄

  • 通過貪心演算法求解,只要最後剩餘的全都是哪個陣營,哪個陣營就獲勝
/**
 * @author: ffzs
 * @Date: 2020/12/11 上午8:50
 */
public class Solution2 {
    public String predictPartyVictory(String senate) {
        char[] cs = senate.toCharArray();
        Queue<Integer> R = new LinkedList<>();
        Queue<Integer> D = new LinkedList<>();
        for (int i = 0; i < cs.length; i++) {
            if (cs[i] == 'R') R.offer(i);
            else D.offer(i);
        }

        while (!R.isEmpty() && !D.isEmpty()) {
            int r = R.poll(), d = D.poll();
            if (r < d) R.offer(cs.length + r);
            else D.offer(cs.length + d);
        }

        return D.isEmpty()? "Radiant" : "Dire";
    }
}

image-20201211091620801

  • 使用陣列代替佇列
  • 遍歷以便後重新構建字串,然後遞迴處理
/**
 * @author: ffzs
 * @Date: 2020/12/11 上午8:09
 */
public class Solution {
    public String predictPartyVictory(String senate) {
        if(senate.length() == 1) return senate.charAt(0) == 'R' ? "Radiant" : "Dire";
        int r = 0, d = 0;
        char[] cs = senate.toCharArray();
        boolean[] ban = new boolean[cs.length];

        for (int i = 0; i < cs.length; i++) {
            if (ban[i]) continue;
            if (cs[i] == 'R') {
                if (d > 0) {
                    d--;
                    ban[i] = true;
                }else {
                    r++;
                }
            }
            else {
                if (r > 0) {
                    r --;
                    ban[i] = true;
                }
                else {
                    d ++;
                }
            }
        }

        int i = 0;
        while (i < cs.length && (r > 0 || d > 0)) {
            if (!ban[i] && cs[i] == 'R' && d > 0) {
                ban[i] = true;
                d--;
            }
            else if (!ban[i] && cs[i] == 'D' && r > 0) {
                ban[i] = true;
                r--;
            }
            i++;
        }
        if(r != 0)
            return "Radiant";
        if(d != 0)
            return "Dire";

        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < ban.length; j++) {
            if (!ban[j]) sb.append(cs[j]);
        }
        return predictPartyVictory(sb.toString());
    }
}

class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.predictPartyVictory("DRRDRDRDRDDRDRDRD"));
    }
}

image-20201211204918602