leetcode算法(239.滑动窗口最大值)

使用 push_back 的优点:

  1. 动态扩容:不需要预先知道结果的数量

  2. 方便快捷:一行代码完成添加操作

  3. 性能良好push_back 的平均时间复杂度是 O(1)

功能:

  • 将一个新元素添加到 vector 的末尾

  • 自动调整 vector 的大小(容量可能会增加)

cpp 复制代码
vector<int> nums;
nums.push_back(10);   // nums 变为 [10]
nums.push_back(20);   // nums 变为 [10, 20]
nums.push_back(30);   // nums 变为 [10, 20, 30]
cpp 复制代码
暴力解法
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        // 存储结果的容器,用于保存每个滑动窗口的最大值
        vector<int> result;
    
        // 处理边界情况:
        // 1. 如果数组为空,直接返回空结果
        // 2. 如果k小于等于0,窗口大小不合法
        // 3. 如果k大于数组长度,窗口无法形成
        if (nums.empty() || k <= 0 || k > nums.size()) {
            return result;  // 返回空结果
        }
    
        // 外层循环:遍历所有可能的窗口起始位置
        // i表示窗口的起始索引,从0开始到nums.size()-k结束
        // 例如:数组长度为8,k=3,则i的取值范围是0~5
        for (int i = 0; i <= nums.size() - k; ++i) {
            // 初始化当前窗口的最大值为窗口的第一个元素
            // maxVal用于记录当前窗口找到的最大值
            int maxVal = nums[i];
        
            // 内层循环:遍历当前窗口内的所有元素
            // j从窗口起始位置i开始,到窗口结束位置i+k-1结束
            // 例如:i=0, k=3时,j遍历0,1,2三个位置
            for (int j = i; j <= i + k - 1; ++j) {
                // 更新当前窗口的最大值
                // 如果当前元素nums[j]大于当前记录的最大值maxVal
                if (nums[j] > maxVal) {
                    // 更新maxVal为更大的值
                    maxVal = nums[j];
                }
                // 注意:这里没有else,因为如果nums[j] <= maxVal,保持maxVal不变
            }
        
            // 内层循环结束后,maxVal就是当前窗口的最大值
            // 将当前窗口的最大值添加到结果容器中
            result.push_back(maxVal);
        }
    
        // 所有窗口处理完毕,返回包含所有窗口最大值的数组
        return result;
    }
};

方法二

cpp 复制代码
class Solution {
private:
    class MyQueue { //单调队列(从大到小)
MyQueue是实现滑动窗口最大值算法的辅助数据结构,它专为Solution类的需求而设计,只在Solution内部使用,不是通用的队列,外部不需要知道或访问这个内部类
cpp 复制代码
class Solution {
private:
    // 自定义单调队列类(内部元素单调递减,队头最大)
    class MyQueue {
    public:
        deque<int> que; // 使用双端队列作为底层容器,支持两端高效插入删除

        // 弹出元素:只有当要弹出的值等于当前队头(最大值)时才真正弹出队头
        void pop(int value) {
            // 若队列非空且当前要移除的元素就是队头元素(即窗口滑动移出的元素是当前最大值)
            if (!que.empty() && value == que.front()) {
                que.pop_front(); // 弹出队头
            }
            // 否则说明要移出的元素不是当前最大值,已在之前被覆盖弹出,无需操作
        }

        // 插入元素:维护队列的单调递减性
        void push(int value) {
            // 当队列非空且新元素大于队尾元素时,不断弹出队尾元素
            // 这样可以确保队列始终保持从队头到队尾的递减顺序
            while (!que.empty() && value > que.back()) {
                que.pop_back(); // 弹出队尾,直到新元素找到合适位置
            }
            que.push_back(value); // 将新元素插入队尾
        }

        // 获取当前队列最大值(即队头元素)
        int front() {
            return que.front();
        }
    };

public:
    // 主函数:滑动窗口最大值
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQueue que; // 创建单调队列实例
        vector<int> result; // 存储结果的数组

        // 初始化:将第一个窗口的k个元素加入队列
        for (int i = 0; i < k; i++) {
            que.push(nums[i]); // 插入元素时会自动维护单调性
        }
        // 第一个窗口的最大值就是当前队头
        result.push_back(que.front());

        // 从第k个元素开始,滑动窗口
        for (int i = k; i < nums.size(); i++) {
            // 窗口向右移动,移除窗口最左侧元素(i-k为移出元素的索引)
            que.pop(nums[i - k]);
            // 将新进入窗口的元素加入队列(i为当前新元素的索引)
            que.push(nums[i]);
            // 当前窗口的最大值即为队头元素
            result.push_back(que.front());
        }
        return result; // 返回所有窗口的最大值集合
    }
};

方法三

cpp 复制代码
cpp
class Solution {
public:

    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        map<int,int> mp;
        vector<int> result;
        int size=nums.size();
        int left=0,right=k-1;
        for(int i=0;i<=k-1;i++) mp[nums[i]]++;
        while(right<size){
            result.push_back(mp.rbegin()->first);
            left++;
            right++;
            if(right>=size) break;
            mp[nums[right]]++;
            mp[nums[left-1]]--;
            while(mp.rbegin()->second==0) mp.erase(mp.rbegin()->first);
        }
        return result;
    }
};
相关推荐
Xの哲學7 小时前
Linux 文件系统一致性: 从崩溃恢复到 Journaling 机制
linux·服务器·算法·架构·边缘计算
wtmReiner7 小时前
山东大学数值计算2026.1大三上期末考试回忆版
笔记·算法
黛色正浓7 小时前
leetCode-热题100-滑动窗口合集(JavaScript)
javascript·算法·leetcode
漫随流水8 小时前
leetcode算法(145.二叉树的后序遍历)
数据结构·算法·leetcode·二叉树
Tony_yitao8 小时前
22.华为OD机试真题:数组拼接(Java实现,100分通关)
java·算法·华为od·algorithm
2501_941875288 小时前
在东京复杂分布式系统中构建统一可观测性平台的工程设计实践与演进经验总结
c++·算法·github
sonadorje8 小时前
梯度下降法的迭代步骤
算法·机器学习
漫随流水8 小时前
leetcode算法(94.二叉树的中序遍历)
数据结构·算法·leetcode·二叉树
王老师青少年编程8 小时前
信奥赛C++提高组csp-s之并查集(案例实践)2
数据结构·c++·并查集·csp·信奥赛·csp-s·提高组
范纹杉想快点毕业8 小时前
嵌入式通信核心架构:从状态机、环形队列到多协议融合
linux·运维·c语言·算法·设计模式