当前位置:首页 > 力扣题解 > 力扣933题解题思路解析,C++代码实现与复杂度分析

力扣933题解题思路解析,C++代码实现与复杂度分析

5天前力扣题解61

截图未命名.jpg 力扣933题解题思路解析,C++代码实现与复杂度分析 队列 双端队列 算法 C++ 数据结构 力扣 第1张

问题本质与核心需求理解

力扣933题要求设计一个RecentCounter类,能够记录特定时间范围内的请求次数。当调用ping(int t)方法时,需要返回过去3000毫秒内(包括当前时刻)发生的所有ping调用次数。这里的核心需求是高效维护时间窗口内的请求记录,并及时过滤失效数据。

解决问题的关键在于选择合适的数据结构。为什么队列结构特别适合此类时间窗口问题?因为请求时间具有单调递增特性,符合先进先出原则(FIFO)。每次新请求到达时,只需要删除窗口外的旧记录,即可快速得到有效请求数。

数据结构选择与时间复杂度分析

使用双端队列(deque)作为核心存储结构具有显著优势。当新请求t到达时,移除所有早于t-3000的记录,将当前t加入队列。这种操作模式保证了每个元素仅被添加和删除各一次,均摊时间复杂度达到O(1)。

数组链表相比,双端队列在头部的快速删除操作优势明显。假设使用普通队列,虽然也能完成基本操作,但当遇到大量历史数据需要清理时,双端队列能更高效地进行批量删除。这种批量处理机制正是优化时间复杂度的关键所在。

代码实现与测试案例验证

示例测试数据:

输入:[1,100, 3001, 3002]输出:[1,2,3, 3]

在实现代码时,需要特别注意边界条件处理。当t=3001时,有效的起始时间是1(3001-3000),此时队列中保留[1,100,3001]三个元素。当后续t=3002到达时,有效起始时间变为2,此时队列中保留[100,300
1,3002]。这种精确的窗口滑动验证了算法的正确性。

为什么不需要考虑请求时间乱序的情况?因为题目明确说明每次ping调用时的参数t是严格递增的,这保证了数据结构中元素的单调性,避免了复杂的时间排序操作。这个前提条件大大简化了算法的实现难度。

C++完整代码实现

class RecentCounter {
public:
   std::deque q;
   int ping(int t) {
      while(!q.empty() && q.front() < t - 3000) {
         q.pop_front();
      }
      q.push_back(t);
      return q.size();
   }
};

代码中如何确保高效执行?双端队列的pop_front()操作时间复杂度为O(1),配合批量删除机制,即使处理大规模数据也能保持高性能。返回队列长度的操作同样具有O(1)时间复杂度,这使得整个方案非常高效。

复杂度分析与优化空间

该算法的时间复杂度均摊为O(1),每个元素最多入队、出队各一次。空间复杂度为O(n),n表示3000毫秒时间窗口内最多的请求次数。在极端情况下,如果每秒有1000次请求,队列最大长度将为3000,内存占用仍然可控。

本文系统性地解析了力扣933题的解题思路,通过队列结构实现高效时间窗口管理。方案具有清晰的逻辑结构、优秀的时间复杂度表现和良好的代码可读性。掌握这种滑动窗口处理范式,能够有效解决同类时间序列相关的算法问题。理解数据结构选择与时间复杂度分析的关联性,是提升算法设计能力的关键所在。


原创内容 转载请注明出处

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。