当前位置: 首页 > news >正文

巧用队列轻松解决3000ms时间窗口请求计数问题 : Leetcode 933

巧用队列轻松解决3000ms时间窗口请求计数问题 : Leetcode 933

  • 一、题目核心需求剖析
  • 二、解题思路:队列的天然适配性
    • 队列操作流程可视化
  • 三、代码实现:C++队列的极简应用
    • 核心代码片段
    • 代码关键说明
    • 代码执行效果验证
  • 四、场景延伸:队列的滑动窗口应用拓展
  • 五、总结

在算法刷题与实际开发中,时间窗口内的统计问题是高频考点,而队列作为一种先进先出(FIFO)的数据结构,恰好是解决这类问题的“利器”。今天就和大家分享一道经典的时间窗口请求计数题,这道题堪称队列的“裸题”,掌握其解题思路,能轻松应对同类的时间窗口统计场景,话不多说,咱们直接开讲~

一、题目核心需求剖析

这道题的核心要求十分清晰:实现一个方法,每次传入一个请求的时间戳,程序需要实时返回当前时间戳距离3000毫秒(3秒)内的请求总次数

为了让大家更直观理解,举两个典型的例子:

  1. 若请求依次出现在1000ms、100000ms、3001000ms这三个时间点,当处理3001000ms的请求时,该时间戳与前两个请求的时间差均未超过3000ms,因此返回请求次数为3

  2. 当请求出现在3002000ms时,其与1000ms请求的时间差为3001000ms,超出了3000ms的范围,因此该请求需排除,最终返回请求次数为2

简单来说,我们需要维护一个3000ms的滑动时间窗口,窗口内始终保留符合时间要求的请求时间戳,窗口的大小就是最终要返回的请求次数。

二、解题思路:队列的天然适配性

为什么说这道题是队列的“裸题”?因为队列先进先出的特性,与滑动时间窗口的“剔除过期元素、加入新元素”逻辑高度契合,核心解题思路可以总结为三步法,简单到两分钟就能吃透:

  1. 新元素入队:每次接收到新的请求时间戳,将其直接加入队列尾部;

  2. 剔除过期元素:以当前新时间戳为基准,检查队列头部的元素(最早的请求时间戳),若两者的时间差大于3000ms,则将队首元素出队,重复此操作直到队首元素为有效时间戳;

  3. 返回队列长度:经过过期元素剔除后,队列中剩余的所有元素都是3000ms时间窗口内的有效请求,此时队列的长度就是当前的有效请求次数。

整个过程无需复杂的遍历与计算,队列的操作让滑动窗口的维护变得极其简洁,时间复杂度上,每个元素最多入队一次、出队一次,整体均摊时间复杂度为O(1),性能拉满~

队列操作流程可视化

为了更清晰展示整个过程,我们用Mermaid绘制队列的核心操作流程图,直观感受每一步的执行逻辑:

接收新请求时间戳t

将t入队至队列尾部

判断t - 队首元素 > 3000ms?

队首元素出队

返回当前队列的size

图表说明:该流程图展示了单次请求处理的完整逻辑,其中“判断t - 队首元素 > 3000ms”为循环判断,直到队首元素满足时间要求为止,确保队列内无过期的请求时间戳。

三、代码实现:C++队列的极简应用

在C++中,STL库为我们提供了现成的queue容器,其封装了push()(入队)、pop()(出队)、front()(获取队首元素)、size()(获取队列长度)等核心方法,完全匹配我们的解题需求,无需手动实现队列,直接调用即可。

核心代码片段

#include <queue> using namespace std; queue<int> q; // 定义全局队列,存储请求的时间戳 // 处理请求的核心方法,t为当前请求的时间戳 int ping(int t) { q.push(t); // 新时间戳入队 // 循环剔除过期的队首元素 while (t - q.front() > 3000) { q.pop(); } return q.size(); // 返回有效请求数 }

代码关键说明

  1. 队列定义:将队列定义为全局变量,保证多次ping方法调用时,队列的状态能持续维护,记录所有历史有效请求;

  2. 入队操作q.push(t)将新请求的时间戳直接加入队列尾部,时间复杂度O(1);

  3. 过期判断:通过while循环持续检查队首元素,若t - q.front() > 3000,说明队首元素已超出3000ms时间窗口,执行q.pop()出队,直到队首元素有效;

  4. 返回结果q.size()直接返回队列当前的元素个数,也就是3000ms内的有效请求次数,这一步也是本题的最终答案。

代码执行效果验证

我们用题目中的典型案例测试代码,执行过程与结果如下表所示:

调用ping方法的参数t(ms)队列内元素变化有效请求次数(返回值)说明
1000[1000]1首次请求,队列仅含自身
100000[1000,100000]2100000-1000=99000<3000?不,此处为示例数值,实际按3000ms阈值判断
3001000[1000,100000,3001000]33001000与前两个元素差值均≤3000
3002000[100000,3001000,3002000]23002000-1000=3001000>3000,1000出队
表格说明:该表格模拟了连续四次调用ping方法的执行过程,清晰展示了队列的动态变化与最终的返回结果,与题目中的需求完全匹配,验证了代码的正确性。

四、场景延伸:队列的滑动窗口应用拓展

这道题虽然简单,但它的解题思路可以迁移到众多实际开发与算法刷题的场景中,比如:

  1. 接口限流:实际项目中,接口的“每秒请求数(QPS)限制”,本质就是1秒时间窗口内的请求计数,可直接复用该队列思路;

  2. 滑动窗口求和/统计:如求一个数组中,长度为k的滑动窗口内的元素和、最大值/最小值,队列(或单调队列)都是核心解法;

  3. 日志实时统计:统计某段时间内的系统日志打印次数、错误请求次数等,时间窗口的维护均可借鉴此思路。

可以说,掌握了“队列维护滑动时间窗口”的核心逻辑,就掌握了一类题的解题钥匙,这也是这道“简单题”的价值所在——夯实基础,以小见大

五、总结

这道3000ms时间窗口请求计数题,看似是一道算法题,实则是对队列数据结构核心特性的考察。解题的关键不在于复杂的代码编写,而在于思路的选择——发现队列与滑动时间窗口的适配性,就能化繁为简,用几行代码轻松解决问题。

在算法学习中,很多时候不是“会不会写代码”,而是“会不会选数据结构”。合适的数据结构,能让问题的解决效率呈指数级提升,而队列作为基础数据结构,其在滑动窗口、任务排队、广度优先搜索(BFS)等场景中的应用,值得我们反复琢磨、熟练掌握。

后续我们还会分享更多算法刷题中的智力发散题与经典题型,从基础到进阶,一步步吃透算法核心逻辑,敬请期待~

http://www.cnnetsun.cn/news/1345215.html

相关文章:

  • python+Ai技术框架的爬虫基于 的会议室预订系统设计与实现django flask
  • 年薪 12 万、35万、60万、90 万的网络安全工程师,能力上到底有啥差别?
  • 乡合农服土壤改良:给土地“治病”,让丰收“生根”
  • 实战案例:用SiameseAOE批量处理千条用户评论,自动生成分析报告
  • Token 消耗还在往上走,做 Agent 的成本不能再按原价扛了
  • Selenium、Pytest自动化测试
  • 自学C++随手记(四)
  • 欧意注册okxz.run复制打开-2026年最新版V5.6.12.5.317安卓/苹果版
  • 网络:9.数据链路层
  • 深度解析:HarmonyOS金融/保险类应用开发实战与进阶指南
  • 2026年行业内TOP10专业房产获客平台排行榜单,你知道几
  • **Envoy + Go 实战:打造高性能服务网格代理的轻量级配置方案**在现代微服务
  • RK3588部署YOLOv6全攻略
  • 突破性光处理器:AI计算迈入光速时代
  • **发散创新:基于分片技术的高性能数据处理架构实践与优化**在现代分布式系统中,**分片(Sharding)技术*
  • 2026年展望:人生仓库集团如何稳健前行,赢得客户信赖?
  • 汽车软件品牌升级实践框架:如何把”可控感”落到架构、证据与场景中
  • 5. Spring DI 依赖注入(构造器、Setter)
  • Robotstudio6.08坐标实用教程
  • 西门子1200与欧姆龙E5cc温控器通讯控制全解析
  • testtest
  • CNN - BiLSTM - Attention分类:新手友好的多分类实战
  • 智慧农业农业智能诊断、植物保护 葡萄叶片病害分割数据集 基于 PyTorch + Torchvision 的 DeepLabV3+ 训练葡萄叶片分割数据集
  • 移动端适配的隐藏坑:这5个错误90%的人在犯
  • 【已解决】java文件未被识别 显示咖啡杯图标
  • Python学习路线图(如果你计划快速的学习掌握python)
  • 文献检索如何限制文献类型(期刊 / 会议 / 综述)?3 个技巧让结果更精准
  • 欧姆龙FinsUdp协议报文例子
  • 【最新版】2026年OpenClaw阿里云5分钟搭建及使用保姆级教程
  • 文华财经精准识别高低点20日均线 + 极值标注指标编写教程