题目

类型:design
image.png

解题思路

  • 根据题意,会在 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]即是答案。

代码

  1. class TopVotedCandidate {
  2. List<Integer> tops;
  3. Map<Integer, Integer> voteCounts;
  4. int[] times;
  5. public TopVotedCandidate(int[] persons, int[] times) {
  6. tops = new ArrayList<Integer>();
  7. voteCounts = new HashMap<Integer, Integer>();
  8. voteCounts.put(-1, -1);
  9. int top = -1;
  10. for (int i = 0; i < persons.length; ++i) {
  11. int p = persons[i];
  12. voteCounts.put(p, voteCounts.getOrDefault(p, 0) + 1);
  13. if (voteCounts.get(p) >= voteCounts.get(top)) {
  14. top = p;
  15. }
  16. tops.add(top);
  17. }
  18. this.times = times;
  19. }
  20. public int q(int t) {
  21. int l = 0, r = times.length - 1;
  22. // 找到满足 times[l] <= t 的最大的 l
  23. while (l < r) {
  24. int m = l + (r - l + 1) / 2;
  25. if (times[m] <= t) {
  26. l = m;
  27. } else {
  28. r = m - 1;
  29. }
  30. }
  31. return tops.get(l);
  32. }
  33. }