题目来源:https://leetcode.com/contest/weekly-contest-103/problems/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);
*/