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 <= persons.length = times.length <= 5000
0 <= persons[i] <= persons.length
times
is a strictly increasing array with all elements in[0, 10^9]
.TopVotedCandidate.q
is called at most10000
times per test case.TopVotedCandidate.q(int t)
is always called witht >= 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);
*/