LeetCode 362. 敲击计数器
题目描述
思路分析
解法一:队列压缩计数(推荐)
核心思路:
- 用队列保存最近 5 分钟内的时间戳与计数对
(timestamp, count)。hit时若与队尾时间戳相同则累加,否则新入队。getHits时弹出过期元素并累计剩余计数。
复杂度分析:
- 时间复杂度:O(1) 均摊,每个元素最多入队出队一次。
- 空间复杂度:O(k),其中 k 为 5 分钟窗口内的不同时间戳数量。
import java.util.ArrayDeque;
import java.util.Deque;
class HitCounter {
private final Deque<int[]> queue = new ArrayDeque<>();
private int total = 0;
public void hit(int timestamp) {
if (!queue.isEmpty() && queue.peekLast()[0] == timestamp) {
queue.peekLast()[1]++;
} else {
queue.addLast(new int[]{timestamp, 1});
}
total++;
}
public int getHits(int timestamp) {
// 清理过期时间戳
while (!queue.isEmpty() && timestamp - queue.peekFirst()[0] >= 300) {
total -= queue.pollFirst()[1];
}
return total;
}
}
type HitCounter struct {
times []hitPair
head int
total int
}
type hitPair struct {
time int
count int
}
func Constructor() HitCounter {
return HitCounter{}
}
func (h *HitCounter) Hit(timestamp int) {
if len(h.times) > h.head && h.times[len(h.times)-1].time == timestamp {
h.times[len(h.times)-1].count++
} else {
h.times = append(h.times, hitPair{time: timestamp, count: 1})
}
h.total++
}
func (h *HitCounter) GetHits(timestamp int) int {
// 清理过期时间戳
for h.head < len(h.times) && timestamp-h.times[h.head].time >= 300 {
h.total -= h.times[h.head].count
h.head++
}
return h.total
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 353. 贪吃蛇 | 中等 | 队列 + 设计 |
| 359. 日志速率限制器 | 简单 | 数据流 |
| 622. 设计循环队列 | 中等 | 队列 |
| 641. 设计循环双端队列 | 中等 | 双端队列 |
| 1472. 设计浏览器历史记录 | 中等 | 数据结构设计 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!