[LeetCode] 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]
.
在一个选举中第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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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:
1 2 3 4 5 6 7 8 9 10 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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++:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #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; } |
类似题目:
All LeetCode Questions List 题目汇总
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构