【LeetCode刷題筆記-33 649:Dota2 參議院】

空、白、發表於2020-12-11

題目:
在這裡插入圖片描述
今天這題一開始我理解錯意思了,導致繞了一點遠路。後來也是想到了用佇列來做這道題。

答案的程式碼看起來還是很簡潔,我自己的多了一些不必要的計算,比如關於一起彈出和+n插入這裡我的就顯得比較臃腫了。

不過我們還是要弄懂怎麼想出來這種做法的。

思路:

1.首先呢,對於這樣的一個投票序列,我們很容易可以想到我們能不能通過模擬這個投票過程來解決這個問題。

2.那麼怎麼模擬呢?假設當前投票的是D,那麼它一定會封禁接下來最早投票的R。這個早晚則取決於DR在字串中的位置。

3.那麼如何判定誰能封禁誰的投票權呢?自然就能想到,要記錄每一個R和每一個D的位置。

4.那麼就會出現一種情況,後出現的R是有可能封禁前面D的下一輪的投票權的,那麼這個關係怎麼表示呢?

5.那麼這個時候就要用到我們的資料結構的知識,去尋找一個能兩兩比較而且還能讓前面元素被重複判定的結構。

於是,就有了佇列

我們可以通過構建D和R的佇列,佇列元素值是在字串中的索引值。每一次比較它們隊首的元素,小的那個先彈出然後+n插入隊伍末尾,方便下一輪投票或者是被後續的R封禁。而較大的那個元素(投票晚於小的),則永久彈出

於是就有了該模擬演算法的框架:

C++程式碼附帶測試:

#include<iostream>
#include<vector> 
#include<string>
using namespace std;

class Solution {
public:
    string predictPartyVictory(string senate) {
        int n = senate.size();
        queue<int> radiant, dire;//建立投票佇列 
        for (int i = 0; i < n; ++i) {
            if (senate[i] == 'R') {
                radiant.push(i);//放入Radiant陣營中,記錄序列值 
            }
            else {
                dire.push(i);//放入Dire陣營中,記錄序列值 
            }
        }
        while (!radiant.empty() && !dire.empty()) {//兩個陣營都還有人剩餘 
            if (radiant.front() < dire.front()) {//判斷當前誰先投 
                radiant.push(radiant.front() + n);//+n最簡單,將比較大的那個人推入下一輪,或者是被隊尾的Radiant禁票 
            }
            else {
                dire.push(dire.front() + n);
            }
            //永久彈出當前元素 
            radiant.pop();
            dire.pop();
        }
        return !radiant.empty() ? "Radiant" : "Dire";
    }
};


int main()
{
	string s = "DRRD";
	Solution solution;
	string ans = solution.predictPartyVictory(s);
	cout<<ans<<endl;
}

相關文章