news 2026/10/13 12:15:34

求滑动窗口的最小值

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
求滑动窗口的最小值

滑动窗口最小值(Sliding Window Minimum)是一个常见的算法问题,与滑动窗口最大值类似,广泛应用于数据流分析、信号处理等领域。本文将介绍滑动窗口最小值的定义、常见解法以及使用堆和双端队列(Deque)实现的C++代码。

问题描述

给定一个整数数组nums和一个滑动窗口大小k,请你找出所有滑动窗口中的最小值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], k = 3 输出: [ -1, -3, -3, -3, 3, 3]

解释:
滑动窗口的位置及其最小值分别为:

窗口位置 最小值 --------------- ----- [1 3 -1] -3 5 3 6 7 -1 1 [3 -1 -3] 5 3 6 7 -3 1 3 [-1 -3 5] 3 6 7 -3 1 3 -1 [-3 5 3] 6 7 -3 1 3 -1 -3 [5 3 6] 7 3 1 3 -1 -3 5 [3 6 7] 3

解法

1. 使用最小堆(Min-Heap)

思路:

使用一个最小堆来维护当前窗口中的元素。堆中存储元素的值和对应的索引。每次滑动窗口时,移除堆中不在窗口范围内的元素,然后堆顶即为当前窗口的最小值。

时间复杂度:O(n log k),其中 n 是数组长度,k 是窗口大小。

空间复杂度:O(k),堆中最多有 k 个元素。

C++ 实现:

#include<iostream>#include<vector>#include<queue>#include<utility>usingnamespacestd;vector<int>slidingWindowMinimum_heap(constvector<int>&nums,intk){vector<int>result;if(nums.empty()||k<=0)returnresult;// 定义最小堆,存储 (值, 索引)priority_queue<pair<int,int>,vector<pair<int,int>>,std::greater<pair<int,int>>>minHeap;for(inti=0;i<nums.size();++i){// 将当前元素加入堆minHeap.emplace(nums[i],i);// 移除堆中不在窗口范围内的元素while(!minHeap.empty()&&minHeap.top().second<i-k+1){minHeap.pop();}// 当窗口形成时,记录最小值if(i>=k-1){result.push_back(minHeap.top().first);}}returnresult;}intmain(){vector<int>nums={1,3,-1,-3,5,3,6,7};intk=3;vector<int>minima=slidingWindowMinimum_heap(nums,k);cout<<"滑动窗口的最小值(堆实现): [";for(size_t i=0;i<minima.size();++i){cout<<minima[i];if(i!=minima.size()-1)cout<<", ";}cout<<"]"<<endl;return0;}

输出:

滑动窗口的最小值(堆实现): [-1, -3, -3, -3, 3, 3]

2. 使用双端队列(Deque)

思路:

使用双端队列来维护当前窗口中的候选最小值的索引。队列中存储的索引对应的值是递增的,这样队首始终是当前窗口的最小值。当新的元素进入窗口时,移除所有比新元素大的元素索引,因为它们不再是可能的最小值。

时间复杂度:O(n),每个元素最多被添加和移除一次。

空间复杂度:O(k),队列中最多有 k 个元素。

C++ 实现:

#include<iostream>#include<vector>#include<deque>usingnamespacestd;vector<int>slidingWindowMinimum_deque(constvector<int>&nums,intk){vector<int>result;if(nums.empty()||k<=0)returnresult;deque<int>dq;// 存储元素的索引for(inti=0;i<nums.size();++i){// 移除队首不在窗口范围内的索引while(!dq.empty()&&dq.front()<i-k+1){dq.pop_front();}// 移除队尾所有比当前元素大的索引while(!dq.empty()&&nums[i]<=nums[dq.back()]){dq.pop_back();}// 添加当前元素的索引到队尾dq.push_back(i);// 当窗口形成时,记录最小值if(i>=k-1){result.push_back(nums[dq.front()]);}}returnresult;}intmain(){vector<int>nums={1,3,-1,-3,5,3,6,7};intk=3;vector<int>minima=slidingWindowMinimum_deque(nums,k);cout<<"滑动窗口的最小值(双端队列实现): [";for(size_t i=0;i<minima.size();++i){cout<<minima[i];if(i!=minima.size()-1)cout<<", ";}cout<<"]"<<endl;return0;}

输出:

滑动窗口的最小值(双端队列实现): [-1, -3, -3, -3, 3, 3]

代码解析

最小堆实现

  1. 堆的定义:

    • 使用priority_queue<pair<int, int>, vector<pair<int, int>>, std::greater<pair<int, int>>>定义一个最小堆,堆中存储元素的值和对应的索引。
  2. 遍历数组:

    • 对于每个元素,将其值和索引加入堆。
    • 移除所有堆顶的索引不在当前窗口范围内的元素。
    • 当窗口形成(即i >= k - 1)时,将堆顶元素的值(即当前窗口的最小值)加入结果。
  3. 时间复杂度:

    • 每个元素进入堆和可能被移出堆的操作都是 O(log k),因此总体时间复杂度为 O(n log k)。

双端队列实现

  1. 队列的定义:

    • 使用deque<int>存储元素的索引,保持队列中的元素对应的值是递增的。
  2. 遍历数组:

    • 移除队首不在窗口范围内的索引。
    • 移除所有队尾比当前元素大的索引,因为这些元素不可能成为未来窗口的最小值。
    • 将当前元素的索引添加到队尾。
    • 当窗口形成时,将队首元素对应的值加入结果。
  3. 时间复杂度:

    • 每个元素最多被添加和移除一次,因此总体时间复杂度为 O(n)。

总结

滑动窗口最小值问题可以通过多种方法实现:

  • 最小堆方法适用于需要频繁查询和动态变化的数据流,但时间复杂度较高(O(n log k))。
  • 双端队列方法更为高效,能够在O(n)的时间复杂度内解决问题,适用于大规模数据处理。

在实际应用中,双端队列方法因其高效性,通常是首选的解决方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 12:15:34

VB6+Access2000库存系统:轻量级本地化事务闭环设计实战

简介&#xff1a;本资源是一份面向高校计算机专业学生、信息管理初学者及中小型企业管理者的技术方案文档&#xff0c;聚焦库存管理系统的设计与实现&#xff0c;解决传统人工库存管理效率低、易出错、难追溯等核心问题。文档完整覆盖系统设计全流程&#xff1a;从管理信息系统…

作者头像 李华
网站建设 2026/10/13 12:12:28

MyBatis多表查询:@One/@Many分步查询与延迟加载源码解析

做业务系统久了&#xff0c;你会觉得多表查询这关是真的绕不过去。以前写 JDBC&#xff0c;两个表字段一多&#xff0c;手动一个字段一个字段 set 进对象&#xff0c;能累到怀疑人生。后来换成 MyBatis&#xff0c;用 Map 接收结果集倒是快&#xff0c;可一旦遇到嵌套对象、集合…

作者头像 李华
网站建设 2026/10/13 12:12:01

工厂园区监控安装报价全解析:从点位设计到13%专票

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/13 12:11:38

Excel SUM函数全解析:从基础求和高阶应用

1. SUM函数本质解析与基础应用在数据处理领域&#xff0c;SUM函数就像会计手中的算盘&#xff0c;是每个数据分析师最先掌握的"生存技能"。这个看似简单的求和工具&#xff0c;实际上蕴含着Excel最基础也最强大的计算逻辑。我至今记得第一次用SUM函数替代手工计算时&…

作者头像 李华