1. 程式人生 > >LeetCode周賽#103 Q4 Online Election (優先佇列)

LeetCode周賽#103 Q4 Online Election (優先佇列)

問題描述

911. Online Election

In an election, the i-th vote was cast for persons[i] at time times[i].

Now, we would like to implement the following query function: TopVotedCandidate.q(int t) will return the number of the person that was leading the election at time t.  

Votes cast at time t will count towards our query.  In the case of a tie, the most recent vote (among tied candidates) wins.

Example 1:

Input: ["TopVotedCandidate","q","q","q","q","q","q"], [[[0,1,1,0,0,1,0],[0,5,10,15,20,25,30]],[3],[12],[25],[15],[24],[8]]
Output: [null,0,1,1,0,0,1]
Explanation: 
At time 3, the votes are [0], and 0 is leading.
At time 12, the votes are [0,1,1], and 1 is leading.
At time 25, the votes are [0,1,1,0,0,1], and 1 is leading (as ties go to the most recent vote.)
This continues for 3 more queries at time 15, 24, and 8.

Note:

  1. 1 <= persons.length = times.length <= 5000
  2. 0 <= persons[i] <= persons.length
  3. times is a strictly increasing array with all elements in [0, 10^9].
  4. TopVotedCandidate.q is called at most 10000 times per test case.
  5. TopVotedCandidate.q(int t)
     is always called with t >= times[0].

------------------------------------------------------------

題意

給出兩個長度為T的陣列times[T]和persons[T]表示T次投票發生的時間和投給的候選人編號。然後給出一個長度為K的時間陣列q[K]表示詢問,求每次詢問時哪一個候選人是勝者。勝者的定義是得票最多的候選人,如果若干個候選人得票相同,則得最後一票最晚的候選人為勝者。總共有N個候選人。

要求給出投票計數器的建構函式和查詢函式。

------------------------------------------------------------

思路

將任務分解:建構函式裡計算每個發生投票的時刻過後的勝者,儲存在長度為T的陣列leader中;查詢函式里根據待查詢的時間位於哪兩次投票之間,查leader陣列得到此時刻的勝者。

建構函式每次判斷勝者如果採用簡單遍歷,則複雜度為O(TN),會TLE. 採用優先佇列優化,每次發生投票就將投票數更新的那個候選人放入優先佇列,此時優先佇列的隊首元素就是這次投票過後的勝者。採用優先佇列優化的建構函式複雜度為O(TlogT).

注意優先佇列第三項比較項要寫成類或結構體,並重載"()"運算子,如果是最大堆,則用"()"實現“小於”的邏輯,如果是最小堆,則用"()"實現“大於”的邏輯(正好是反過來的)。

------------------------------------------------------------

程式碼

class TopVotedCandidate {
public:
    struct node {
        int id, num, last;                  // id: voter id, num: votes number, last: last votes time
        
        node (void) {}
        node (int ii, int nn, int ll): id(ii), num(nn), last(ll) {}
    };
    
    struct NodeCompare {
        bool operator() (const node &n1, const node &n2)    // check leader   
        {
            if (n1.num < n2.num)
            {
                return true;
            }
            else if (n1.num == n2.num && n1.last < n2.last)
            {
                return true;
            }
            return false;
        }
    };
    
    vector<int> leader;                 // leader at times when vote happens
    vector<int> mytime;                 // times when vote happens
    int votes[5005];                    // votes for every candidate
    int lasts[5005];                    // last vote time for every candidate
    priority_queue<node, vector<node>, NodeCompare> pq;            // for fast leader selection
    TopVotedCandidate(vector<int> persons, vector<int> times) {
        mytime = times;
        memset(votes, 0, sizeof(votes));
        memset(lasts, 0, sizeof(lasts));
        int i, j, len = times.size(), maxid = -1;
        for (i=0; i<len; i++)
        {
            votes[persons[i]]++;
            lasts[persons[i]] = times[i];
            pq.push(node(persons[i], votes[persons[i]], lasts[persons[i]]));
            maxid = pq.top().id;
            leader.push_back(maxid);
        }
        mytime.push_back(1000000000+5); // maxium time possible
    }
    
    int q(int t) {
        int i, len = mytime.size();
        for (i=0; i<len-1; i++)
        {
            if (t >= mytime[i] && t < mytime[i+1])
            {
                return leader[i];
            }
        }
    }
};

/**
 * Your TopVotedCandidate object will be instantiated and called as such:
 * TopVotedCandidate obj = new TopVotedCandidate(persons, times);
 * int param_1 = obj.q(t);
 */