【每日一题】Day0002:力扣题库NO.911. 在线选举

先吐槽下编号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<Integer, Integer> 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<this.times.length-1;i++){
            if(this.times[i] <= t && this.times[i+1] > 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<times.length; i++){
            tempTickerts[persons[i]]++;
            // 如果当前最大票数和候选人发生变化,则记录
            if(tempTickerts[persons[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<times.length;i++){
                if(t<times[i]){
                    break;
                }
            }
            return maxTicketsPersonPerTime[i-1];
        }
    }

}

/**
 * Your TopVotedCandidate object will be instantiated and called as such:
 * TopVotedCandidate obj = new TopVotedCandidate(persons, times);
 * int param_1 = obj.q(t);
 */

测试并修改了一次之后,成功通过~

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值