题目
类型:design
解题思路
- 根据题意,会在
times[i]
时刻为persons[i]
候选人增加一票。 - 利用
times
数组严格递增,可以在处理times
时(模拟加票过程),使用一个变量 val 来维护当前得票的最大数量,使用 list 来记录不同时刻点的候选人交替情况。 - 起始时 val = 0,当出现票数大于等于 val 时,往 list 追加二元组记录
list[idx] = (times[i], persons[i])
,并更新 val。
每个list[idx]
代表了当前候选人list[idx][1]
的首次当选时刻为 list[idx][0]
。
若 i = list[idx][0]
, j = list[idx + 1][0]
,则意味着在时间段 [i, j)
内当选的候选人为list[idx][1]
。
在查询时,只需要通过「二分」找到 list 中满足 list[i][0]<=t
的分割点 r(最大下标),取list[r][1]
即是答案。
代码
class TopVotedCandidate {
List<Integer> tops;
Map<Integer, Integer> voteCounts;
int[] times;
public TopVotedCandidate(int[] persons, int[] times) {
tops = new ArrayList<Integer>();
voteCounts = new HashMap<Integer, Integer>();
voteCounts.put(-1, -1);
int top = -1;
for (int i = 0; i < persons.length; ++i) {
int p = persons[i];
voteCounts.put(p, voteCounts.getOrDefault(p, 0) + 1);
if (voteCounts.get(p) >= voteCounts.get(top)) {
top = p;
}
tops.add(top);
}
this.times = times;
}
public int q(int t) {
int l = 0, r = times.length - 1;
// 找到满足 times[l] <= t 的最大的 l
while (l < r) {
int m = l + (r - l + 1) / 2;
if (times[m] <= t) {
l = m;
} else {
r = m - 1;
}
}
return tops.get(l);
}
}