LeetCode刷题记录(三十二):最近的请求次数

128 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

最近的请求次数

image.png

题目解析

题目难度:简单

题目素材解析

从题目的描述来看,只提供了一个素材。

  1. 提供了时间t参数。

并且保证多次调用ping方法时,t的值一直会递增;也就是说每一次执行ping方法时,t的值相对来说都是最大的。

我的解读

我对本道题的解读,其实也并不难理解。

其实预期结果就是,在执行ping方法时,要计算出当前对象实例的历史ping方法传入的历史值,有多少个是在[t-3000, t]内。

就是这个示例可能会比较迷惑。

比如下面这个:

输入: ["RecentCounter", "ping", "ping", "ping", "ping"] [[], [1], [100], [3001], [3002]]

这里要简单说一下,第一行是执行方法或者new对象;

第二行是传入的参数。

解题思路

由上面的解读,来解答一下这道题的思路:

一共分为两个关键点:

其一,保存历史值。

其二,从历史值中获得符合要求值的个数。

初版代码中,是通过List来存储历史值,并且通过暴力循环的方式来获得结果个数。

完善代码中,也是通过List来存储历史值,不过因为优化的工作在其中,利用二分法来获得最终位置,以此来计算结果个数。

代码

初版代码:

class RecentCounter {
    
    List<Integer> list = null;
    
    public RecentCounter() {
        list = new ArrayList<>();
    }

    public int ping(int t) {
        list.add(t);
        int a = 0;
        int mint = t - 3000;
        for (Integer tb : list) {
            if (tb >= mint) {
                a += 1;
            }
        }
        return a;
    }

}

完善后的代码:

class RecentCounter {
    
    List<Integer> list = null;
    
    public RecentCounter() {
        list = new ArrayList<>();
    }

    public int ping(int t) {
        list.add(t);
        int mint = t - 3000;
        int l = 0, r = list.size();
        while (l < r){
            int n = (r + l) / 2;
            Integer tb = list.get(n);
            if (tb >= mint) {
                r = n;
            }else{
                l = n + 1;
            }
        }
        return list.size() - l;
    }

}

执行结果

前期使用的方法是通过暴力循环来解决的,所以效率比较慢;

使用二分法完善后的执行结果,明显会好一些,但是终究是没有队列处理的更快。

image.png

Java代码本地执行

Java本地可调试代码,请参考github/Ijiran,可通过索引看到相应代码。