在C++中,高效解决滑动窗口最大值问题通常使用**双端队列(deque)** 实现单调队列算法。以下是完整实现及详细注释:
#include <vector>
#include <deque>
#include <iostream>
std::vector<int> maxSlidingWindow(const std::vector<int>& nums, int w) {
if (nums.empty() || w <= 0) return {};
std::vector<int> result;
std::deque<int> dq; // 存储索引,队列单调递减(队头最大)
for (int i = 0; i < nums.size(); ++i) {
// 步骤1:移除队尾小于当前元素的索引(保持单调性)
while (!dq.empty() && nums[dq.back()] <= nums[i]) {
dq.pop_back();
}
// 步骤2:当前索引入队
dq.push_back(i);
// 步骤3:移除超出窗口的队头索引
if (dq.front() <= i - w) {
dq.pop_front();
}
// 步骤4:当窗口形成时记录最大值(队头元素)
if (i >= w - 1) {
result.push_back(nums[dq.front()]);
}
}
return result;
}
// 示例用法
int main() {
std::vector<int> nums = {1, 3, -1, -3, 5, 3, 6, 7};
int w = 3;
std::vector<int> maxInWindows = maxSlidingWindow(nums, w);
// 输出结果: 3 3 5 5 6 7
for (int val : maxInWindows) {
std::cout << val << " ";
}
return 0;
}
### 算法核心思想:
1. **双端队列维护索引**
- 队列中存储数组索引,且对应的元素值**单调递减**
- 队头始终是当前窗口最大值的索引
2. **四步操作遍历数组**:
- **移除冗余队尾**:循环移除队尾小于当前元素的索引(保证单调性)
- **当前索引入队**:将当前元素索引加入队尾
- **清理过期队头**:若队头索引超出窗口左边界则移除
- **记录窗口最大值**:当窗口完整时(`i >= w-1`),队头即为最大值
### 时间复杂度:
- **O(n)**:每个元素最多入队和出队各一次
- **空间复杂度 O(w)**:双端队列最多存储 `w` 个索引
### 关键点解析:
- **单调队列**:通过维护递减序列,避免每次窗口滑动都重新扫描
- **索引存储**:队列存索引而非值,便于检测窗口边界
- **边界处理**:窗口形成条件 `i >= w-1` 和过期索引检查 `dq.front() <= i - w`
此实现是滑动窗口类问题的最优解,适用于大数据流处理等场景。