Easy
题目描述
你有一个 RecentCounter 类来统计特定时间范围内最近的请求次数。
请你实现 RecentCounter 类:
RecentCounter()初始化计数器,请求数为 0 。int ping(int t)在时间t添加一个新请求,其中t表示以毫秒为单位的某个时间,并返回过去3000毫秒内发生的所有请求数(包括新请求)。确切地说,返回在[t-3000, t]内发生的请求数。
保证每次对 ping 的调用都使用比之前调用更大的 t 值。
示例 1:
输入:
["RecentCounter", "ping", "ping", "ping", "ping"]
[[], [1], [100], [3001], [3002]]
输出:
[null, 1, 2, 3, 3]
解释:
RecentCounter recentCounter = new RecentCounter();
recentCounter.ping(1); // requests = [1], 范围是 [-2999,1],返回 1
recentCounter.ping(100); // requests = [1, 100], 范围是 [-2900,100],返回 2
recentCounter.ping(3001); // requests = [1, 100, 3001], 范围是 [1,3001],返回 3
recentCounter.ping(3002); // requests = [1, 100, 3001, 3002], 范围是 [2,3002],返回 3
提示:
1 <= t <= 10^9- 保证每次对
ping调用所使用的t值都 严格递增 - 至多调用
ping方法10^4次
解题思路
解题思路
这道题要求我们统计过去 3000 毫秒内的请求次数。由于每次调用 ping 的时间 t 都是严格递增的,我们可以利用这个特性来优化解决方案。
方法分析:
暴力解法:使用数组存储所有时间戳,每次
ping时遍历数组统计范围内的请求数。时间复杂度 O(n),空间复杂度 O(n)。队列优化(推荐):使用队列存储时间戳,利用时间严格递增的特性。每次
ping时,先移除队列中超出 3000 毫秒范围的旧请求,然后添加新请求,返回队列长度即可。
队列解法的核心思想:
- 队列保存所有在有效时间窗口内的请求时间戳
- 由于时间严格递增,队列中的时间戳天然有序
- 每次新请求到来时,从队头移除所有过期的请求(时间小于
t-3000的请求) - 将新请求时间加入队尾,返回队列当前大小
这种方法的优势是:
- 时间复杂度:平均 O(1),最坏 O(n)(当需要清理大量过期请求时)
- 空间复杂度:O(W),其中 W 是时间窗口内的最大请求数,最多 3001 个
代码实现
class RecentCounter {
private:
queue<int> requests;
public:
RecentCounter() {
}
int ping(int t) {
requests.push(t);
while (!requests.empty() && requests.front() < t - 3000) {
requests.pop();
}
return requests.size();
}
};
class RecentCounter:
def __init__(self):
self.requests = []
def ping(self, t: int) -> int:
self.requests.append(t)
while self.requests and self.requests[0] < t - 3000:
self.requests.pop(0)
return len(self.requests)
public class RecentCounter {
private Queue<int> requests;
public RecentCounter() {
requests = new Queue<int>();
}
public int Ping(int t) {
requests.Enqueue(t);
while (requests.Count > 0 && requests.Peek() < t - 3000) {
requests.Dequeue();
}
return requests.Count;
}
}
var RecentCounter = function() {
this.requests = [];
};
RecentCounter.prototype.ping = function(t) {
this.requests.push(t);
while (this.requests.length > 0 && this.requests[0] < t - 3000) {
this.requests.shift();
}
return this.requests.length;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(1) 均摊 | 每个请求最多被添加和移除一次 |
| 空间复杂度 | O(W) | W 为时间窗口内的最大请求数,最多 3001 个 |