[路飞]_每天刷leetcode_57( 最近的请求次数 Number of Recent Calls)

151 阅读2分钟

「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战

最近的请求次数 Number of Recent Calls

LeetCode传送门933. 最近的请求次数

写一个 RecentCounter 类来计算特定时间范围内最近的请求。

请你实现 RecentCounter 类:

  • RecentCounter() 初始化计数器,请求数为 0 。

  • int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。

保证 每次对 ping 的调用都使用比之前更大的 t 值。

You have a RecentCounter class which counts the number of recent requests within a certain time frame.

Implement the RecentCounter class:

  • RecentCounter() Initializes the counter with zero recent requests.
  • int ping(int t) Adds a new request at time t, where t represents some time in milliseconds, and returns the number of requests that has happened in the past 3000 milliseconds (including the new request). Specifically, return the number of requests that have happened in the inclusive range [t - 3000, t].

It is guaranteed that every call to ping uses a strictly larger value of t than the previous call.

Constraints:

  • 1<=t<=1091 <= t <= 10^9
  • Each test case will call ping with strictly increasing values of t.
  • At most 10410^4 calls will be made to ping.

思考线


解题思路

我们先要读懂题意。我们要记录一下在过去3000毫秒内发生的所有请求数。

在这个题目里面,我们的请求时间是依次递增的。

这样我们就很容易用数组来实现这个解法。

首先我们用数组把所有的请求都push进去。

然后查找数组里和当前ping的时间相差3000ms以内的元素的个数。

第一版我的代码如下:

class RecentCounter {
    times: number[]
    constructor() {
        this.times = [];
    }

    ping(t: number): number {
        this.times.push(t)
        return this.times.filter(item => t - item <= 3000).length
    }
}
/**
 * Your RecentCounter object will be instantiated and called as such:
 * var obj = new RecentCounter()
 * var param_1 = obj.ping(t)
 */

上面这个代码有一个条件我们没用用上,那就是,时间是递增的。我们所有查找的大于3000ms的数据都不会有再次被用到的可能性。所以我们可以多做一步操作,让times的值只保留在3000ms以内的元素。

优化后的代码如下


class RecentCounter {
    times: number[]
    constructor() {
        this.times = [];
    }

    ping(t: number): number {
        this.times.push(t)
        return (this.times = this.times.filter(item => t - item <= 3000)).length
    }
}

面对上面的代码,会发现,我们其实不用每次都filter的。因为我们每次只需要确定确保数组中第0号元素是小于3000ms的即可。如果这样的话,我们为啥不用个队列来保存数据呢?

于是我就得到了这样的代码

class RecentCounter {
    times: number[]
    constructor() {
        this.times = [];
    }

    ping(t: number): number {
        this.times.push(t)
        while(t - this.times[0] > 3000) {
            this.times.shift()
        }
        return this.times.length
    }
}

时间复杂度

O(k) : K为 ping的次数。

这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。