1. 程式人生 > 其它 >649. Dota2參議院 Java 詳細題解

649. Dota2參議院 Java 詳細題解

技術標籤:演算法刷題演算法javaleetcode陣列

649. Dota2 參議院

一、原題題目

1.1 題目

​ Dota2 的世界裡有兩個陣營:Radiant (天輝)和 Dire(夜魘)。Dota2 參議院由來自兩派的參議員組成。現在參議院希望對一個 Dota2 遊戲裡的改變作出決定。他們以一個基於輪為過程的投票進行。在每一輪中,每一位參議員都可以行使兩項權利中的一項:

  1. 禁止一名參議員的權利:參議員可以讓另一位參議員在這一輪和隨後的幾輪中喪失所有的權利

  2. 宣佈勝利:如果參議員發現有權利投票的參議員都是同一個陣營的,他可以宣佈勝利並決定在遊戲中的有關變化。

​ 給定一個字串代表每個參議員的陣營。字母 “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 演算法執行結果

表格標籤示例

四、總結分析

​ 個人感覺這個題目是題目意思有點讓人費解,讀懂題目意思後思路還是挺簡單的。