2021-12-11每日一题

911. 在线选举

给你两个整数数组 persons 和 times 。在选举中,第 i 张票是在时刻为 times[i] 时投给候选人 persons[i] 的。

对于发生在时刻 t 的每个查询,需要找出在 t 时刻在选举中领先的候选人的编号。

在 t 时刻投出的选票也将被计入我们的查询之中。在平局的情况下,最近获得投票的候选人将会获胜。

实现 TopVotedCandidate 类:

  • TopVotedCandidate(int[] persons, int[] times) 使用 persons 和 times 数组初始化对象。
  • int q(int t) 根据前面描述的规则,返回在时刻 t 在选举中领先的候选人的编号。
 

示例:

输入:
["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]]
输出:
[null, 0, 1, 1, 0, 0, 1]

解释:
TopVotedCandidate topVotedCandidate = new TopVotedCandidate([0, 1, 1, 0, 0, 1, 0], [0, 5, 10, 15, 20, 25, 30]);
topVotedCandidate.q(3); // 返回 0 ,在时刻 3 ,票数分布为 [0] ,编号为 0 的候选人领先。
topVotedCandidate.q(12); // 返回 1 ,在时刻 12 ,票数分布为 [0,1,1] ,编号为 1 的候选人领先。
topVotedCandidate.q(25); // 返回 1 ,在时刻 25 ,票数分布为 [0,1,1,0,0,1] ,编号为 1 的候选人领先。(在平局的情况下,1 是最近获得投票的候选人)。
topVotedCandidate.q(15); // 返回 0
topVotedCandidate.q(24); // 返回 0
topVotedCandidate.q(8); // 返回 1

 

提示:

  • 1 <= persons.length <= 5000
  • times.length == persons.length
  • 0 <= persons[i] < persons.length
  • 0 <= times[i] <= 109
  • times 是一个严格递增的有序数组
  • times[0] <= t <= 109
  • 每个测试用例最多调用 104 次 q
 1 import java.util.HashMap;
 2 
 3 public class TopVotedCandidate {
 4     int n=0;
 5     int[] ans,time;
 6     public TopVotedCandidate(int[] persons, int[] times) {
 7         ans=new int[times.length];
 8         n= times.length;
 9         time=times;
10         //ans记录每个时间点票数最多的人
11         int indicate=-1,MAX=-1;
12         HashMap<Integer, Integer> map = new HashMap<>();
13         //记录每个人的票数,维护每个时间段票数最多者
14         for (int i = 0; i < persons.length; i++) {
15             map.put(persons[i],map.getOrDefault(persons[i],0)+1);
16             if (indicate==-1){
17                 indicate=persons[i];
18                 MAX=map.get(persons[i]);
19             }else if (map.get(persons[i])>=MAX){
20                 MAX=map.get(persons[i]);
21                 indicate=persons[i];
22             }
23             //选出最多者的号码,并存入ans数组中
24             ans[i]=indicate;
25         }
26     }
27 
28     public int q(int t) {
29         //二分查找t时间最近的时间点
30         int l=0,r=n-1;
31         while (l<=r){
32             int mid=(l+r)/2;
33             if (time[mid]>t){
34                 r=mid-1;
35             }else if(time[mid]<t){
36                 l=mid+1;
37             }else{
38                 return ans[mid];
39             }
40         }
41         return ans[r];
42     }
43 
44     public static void main(String[] args) {
45         int[] p={0, 1, 0, 1, 1};
46         int[] t={24,29,31,76,81};
47         int[] test={28,24,29,77,30,25,76,75,81,80};
48         TopVotedCandidate topVotedCandidate = new TopVotedCandidate(p, t);
49         for (int j : test) {
50             System.out.println(topVotedCandidate.q(j));
51         }
52     }
53 }

需要注意的是二分法寻找左边界的处理、

while (l<=r)对应l==r 的情况,所以返回ans[r]和ans[l]都是一样的
l<=r对应的r为n-1,如果r=n,则应为l<r
同时也对应mid是否应该加减1
上一篇:每日一题-911. 在线选举_JavaScript


下一篇:C#中的浅表副本Clone与深拷贝Clone