先吐槽下编号911。这题难度是中等,不过在看到题目的瞬间,思路还是很清晰的。题目连接如下:
力扣https://leetcode-cn.com/problems/online-election/初期思路:
1. times数组是一个严格递增的有序数组,public int q(int t) 根据t很容易找到对应的下标
2. 根据下标能够得到一个q方法涉及到的persons的子数组
3. 记录这个子数组里每个元素(即候选人编号)出现的次数,以候选人编号为键,以出现的次数为值,构成一个hashmap
4. 将这个hashmap最大值对应的键输出即可
5. 考虑到存在最大值相等的情况最近获得投票的候选人将会获胜,因此需要判断一下两个不同编号候选人在步骤2里得到的子数组,谁的最后一票更靠后。
具体代码如下。
package cn.daycode.leetcode;
import java.util.HashMap;
import java.util.Iterator;
class TopVotedCandidate {
int[] persons;
int[] times;
public TopVotedCandidate(int[] persons, int[] times) {
this.persons = persons;
this.times = times;
}
public int q(int t) {
HashMap hashMap = new HashMap<>();
int lastPerson = -1; // 记录最后一张票的所有者
int flag = findFlag(t);
for(int i = 0; i <= flag; i++){
if(hashMap.containsKey(this.persons[i])){
lastPerson = this.persons[i];
hashMap.put(this.persons[i],hashMap.get(this.persons[i])+1);
}else {
lastPerson = this.persons[i];
hashMap.put(this.persons[i],1);
}
}
int maxPersoni = -1;
int maxTicketNum = -1;
Iterator iter = hashMap.entrySet().iterator();
while (iter.hasNext()) {
HashMap.Entry entry = (HashMap.Entry) iter.next();
int ticketNum = (int) entry.getValue();
int personi = (int) entry.getKey();
if(ticketNum > maxTicketNum){
maxTicketNum = ticketNum;
maxPersoni = personi;
}else if(ticketNum == maxTicketNum){
maxPersoni = judgeMoreRecently(personi,maxPersoni,flag);
}
}
return maxPersoni;
}
// 判断哪位候选人是最近获得选票的
private int judgeMoreRecently(int p1, int p2, int flag){
int p1Flag = -1;
int p2Flag = -1;
for(int i=0;i<=flag;i++){
if(persons[i] == p1){
p1Flag = i;
}else if(persons[i] == p2){
p2Flag = i;
}
}
return p1Flag>p2Flag?p1:p2;
}
// 根据t找到对应的times下标并返回
private int findFlag(int t){
for(int i=0;i t){
return i;
}
}
return this.times.length-1;
}
}
/**
* Your TopVotedCandidate object will be instantiated and called as such:
* TopVotedCandidate obj = new TopVotedCandidate(persons, times);
* int param_1 = obj.q(t);
*/
用来测试的main方法里的内容我删掉了,需要测试的可以自己准备正确的persons和times数组。代码应该没有问题能够实现功能,但是在跑最后几个例子的时候遗憾地报了“超出时间限制”的问题。回顾了一下思路确实效率太低,多次不必要的遍历和判断。
最初的另外一条思路本来我是觉得有点投机取巧,但是这条路不行只能另辟蹊径了。
思路2:
1. 遍历一边times和persons,将每个times时间点对应票数最多的候选人的编号记录在一个新准备的数组里
2. 根据t找到对应下标并输出
感觉上这个方法更加直接,不过前提也是时间是严格递增的。
代码如下:
package cn.daycode.leetcode;
class TopVotedCandidate {
int[] persons;
int[] times;
// 这个数组用来存放每次times对应时间点的票最多的候选人的编号
int[] maxTicketsPersonPerTime;
public TopVotedCandidate(int[] persons, int[] times) {
this.persons = persons;
this.times = times;
maxTicketsPersonPerTime = new int[persons.length];
int tempMaxTicketNumber = 1; // 记录暂时的最高票数
int tempMaxPerson = persons[0]; // 记录暂时的最高票候选人
// tempTickerts数组的下标是候选人编号,里面存放的是候选人的的票
int[] tempTickerts = new int[persons.length];
maxTicketsPersonPerTime[0]=persons[0]; // 暂时的最高票候选人就是person[0]
tempTickerts[persons[0]]++; // person[0]记一票
// 遍历数组,将每个times[i]时最多票数的候选人id记录在maxTicketsPerson[i]里
for(int i=1; i= tempMaxTicketNumber){
tempMaxPerson = persons[i];
tempMaxTicketNumber = tempTickerts[persons[i]];
}
// 将这次结果记入max
maxTicketsPersonPerTime[i] = tempMaxPerson;
}
}
// 根据t找到对应下标,输出maxTicketsPersonPerTime对应下标里存放的候选人编号即可
public int q(int t) {
// t大于times最大值的话,输出maxTicketsPersonPerTime最后一个元素即可
if(t >= times[times.length-1]){
return maxTicketsPersonPerTime[times.length-1];
}else{
// 否则找到对应下标,输出对应maxTicketsPersonPerTime对应位置的元素
int i=0;
for(;i
测试并修改了一次之后,成功通过~