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 <= 50000 <= persons[i] <= persons.lengthtimesis a strictly increasing array with all elements in[0, 10^9].TopVotedCandidate.qis called at most10000times per test case.TopVotedCandidate.q(int t)is always called witht >= times[0].
在一个选举中第i次投票的情况为persons[i]和times[i],实现一个函数能实现在时间t返回得票数多的lead。
解法:设置一个目前得票最多的变量count,先循环得票人和时间,用hashmap或数组数组统计每个人的得票数,如果次数大于count,则更新count,用数组记录到目前时间得票最多的人(按时间顺序排列的目前得票多的人)。查找某一时间点得票最多的人时,用二分法查找按时间排序的数组。
G家:给一个vote list=[(a, 100), (b, 150), (a, 200)] #(name, timestamp) 和时间T 找T时间之前, 得票数最高的人(或任一得票数最高的人) ex: T=100 -> a, T=150 -> a or b, T=200 -> a. 用map去存每个char对应的频率,如果当前的timestamp小于给定的时间T,就把当前char的频率 + 1, 最后找出map里面value最大的key
Followup1: 多给一个input K, 找T时间之前, Top K 得票数的人. 和上一个题目一样只是找出map里面前K个value最大的key
Followup2: 一样给vote list, K, 但这次给Top K list, 找时间T. 每次添加一张票以后,map里取topk个和topklist比较一下
Java: Basic, easy to understand.
class TopVotedCandidate {
int[] leading;
int[] time;
public TopVotedCandidate(int[] persons, int[] times) {
time = times;
leading = new int[persons.length];
Map<Integer, Integer> map = new HashMap<>();
for (int n : persons){
map.put(n, 0);
}
int max = persons[0];
for (int i = 0; i < times.length; i++){
if (i == 0){
map.put(persons[i], 1);
leading[i] = persons[i];
}else{
map.put(persons[i], map.get(persons[i]) + 1);
if (max != persons[i] && map.get(persons[i]) >= map.get(max)){
max = persons[i];
}
leading[i] = max;
}
//System.out.print(leading[i]);
}
}
public int q(int t) {
int i = 0, j = time.length;
while (i < j){
int mid = i + (j - i) / 2;
if (time[mid] <= t){
i = mid + 1;
}else{
j = mid;
}
}
return leading[i - 1];
}
}
Java:
class TopVotedCandidate {
List<List<Vote>> A;
public TopVotedCandidate(int[] persons, int[] times) {
A = new ArrayList();
Map<Integer, Integer> count = new HashMap();
for (int i = 0; i < persons.length; ++i) {
int p = persons[i], t = times[i];
int c = count.getOrDefault(p, 0) + 1;
count.put(p, c);
while (A.size() <= c)
A.add(new ArrayList<Vote>());
A.get(c).add(new Vote(p, t));
}
}
public int q(int t) {
// Binary search on A[i][0].time for smallest i
// such that A[i][0].time > t
int lo = 1, hi = A.size();
while (lo < hi) {
int mi = lo + (hi - lo) / 2;
if (A.get(mi).get(0).time <= t)
lo = mi + 1;
else
hi = mi;
}
int i = lo - 1;
// Binary search on A[i][j].time for smallest j
// such that A[i][j].time > t
lo = 0; hi = A.get(i).size();
while (lo < hi) {
int mi = lo + (hi - lo) / 2;
if (A.get(i).get(mi).time <= t)
lo = mi + 1;
else
hi = mi;
}
int j = Math.max(lo-1, 0);
return A.get(i).get(j).person;
}
}
class Vote {
int person, time;
Vote(int p, int t) {
person = p;
time = t;
}
}
Java:
Map<Integer, Integer> m = new HashMap<>();
int[] time;
public TopVotedCandidate(int[] persons, int[] times) {
int n = persons.length, lead = -1;
Map<Integer, Integer> count = new HashMap<>();
time = times;
for (int i = 0; i < n; ++i) {
count.put(persons[i], count.getOrDefault(persons[i], 0) + 1);
if (i == 0 || count.get(persons[i]) >= count.get(lead)) lead = persons[i];
m.put(times[i], lead);
}
}
public int q(int t) {
int i = Arrays.binarySearch(time, t);
return i < 0 ? m.get(time[-i-2]) : m.get(time[i]);
}
Python:
class TopVotedCandidate(object):
def __init__(self, persons, times):
self.A = []
self.count = collections.Counter()
for p, t in zip(persons, times):
self.count[p] = c = self.count[p] + 1
while len(self.A) <= c: self.A.append([])
self.A[c].append((t, p))
def q(self, t):
lo, hi = 1, len(self.A)
while lo < hi:
mi = (lo + hi) / 2
if self.A[mi][0][0] <= t:
lo = mi + 1
else:
hi = mi
i = lo - 1
j = bisect.bisect(self.A[i], (t, float('inf')))
return self.A[i][j-1][1]
Python:
def __init__(self, persons, times):
self.leads, self.times, count = [], times, {}
lead = -1
for t, p in zip(times, persons):
count[p] = count.get(p, 0) + 1
if count[p] >= count.get(lead, 0): lead = p
self.leads.append(lead)
def q(self, t):
return self.leads[bisect.bisect(self.times, t) - 1]
Python:
class TopVotedCandidate:
def __init__(self, persons, times):
votes = collections.defaultdict(int)
winner = 0
self.winners = [None] * len(times)
self.times = times
for i, person in enumerate(persons):
votes[person] += 1
if votes[person] >= votes[winner]:
winner = person
self.winners[i] = winner
def q(self, t):
return self.winners[bisect.bisect(self.times, t) - 1]
C++:
map<int, int> m;
TopVotedCandidate(vector<int> persons, vector<int> times) {
int n = persons.size(), lead = -1;
unordered_map<int, int> count;
for (int i = 0; i < n; ++i) m[times[i]] = persons[i];
for (auto it : m) {
if (++count[it.second] >= count[lead])lead = it.second;
m[it.first] = lead;
}
}
int q(int t) {
return (--m.upper_bound(t))-> second;
}
G家:
Give a vote list = [(a, 100), (b, 150), (a, 200)] # (name, timestamp) and time T. Find the highest number of votes (or anyone with the highest number of votes) at T
ex: T = 100 -> a, T = 150 -> a or b, T = 200 -> a
Followup1: give one more input K, find Top K votes at T
Followup2: the same vote list, K, but given the Top K votes list, find the time T.
For the first question, just travers the vote list and if vote.T <= T increment
the vote for person vote.Name. While doing that maximize the vote number.
(O(n*l) time, O(c*l) space, c is the number of candidates, l is average length of name)
follow-up 1: instead of maximizing one, keep the hashtable with votes[person] = no. votes
now, put that into a vector and find the k-th element (using e.g. quicksort's partion
method which is linear)
(O(n*l) time, O(c*l) space)
follow-up 2: I assume given are the top K candidates at a certain time T I have to find.
I have to keep all candidates sorted at each step and compare the top k of them with
the given list. The first part (keeping candidates sorted at each step) can be done
using a balanced binary-tree, so I have O(n*lg(n)+n*l) for creating and maintaining that tree.
(I will have to transpose the name into an integer, and have a nameId instead of the
string in the tree)
Then I would have k compare's per iteration, which is then O(k*n*lg(n)+n*l). the factor k
I can get rid of if I implement the tree in a way, so I monitor when elements enter and
leave the top k. If one of the desired candidates enters top k, I reduce the amount of
candidates I need in top k, if one leaves, I increment back. If that counter (which
starts with k) is 0 I'm done, I found the first time where the desired condition happend.
C:
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
struct Vote
{
int time_;
string name_;
};
string find_top_at_time(const vector<Vote>& votes, int time) {
unordered_map<string, int> votes_per_name;
string max_votes_name;
int max_votes_count = -1;
for (const Vote& vote : votes) { // O(n)
if (vote.time_ <= time) {
auto it = votes_per_name.find(vote.name_); // O(l)
if (it == votes_per_name.end()) {
it = votes_per_name.insert({ vote.name_, 0 }).first; // O(l) compensated
}
it->second++;
if (it->second > max_votes_count) {
max_votes_count = it->second;
max_votes_name = vote.name_; // O(l)
}
}
}
return max_votes_name;
}
类似题目: