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;
    }
};
相关推荐
你撅嘴真丑18 小时前
求10000 以内的阶乘 与 字符串最大跨距
数据结构·c++·算法
Figo_Cheung18 小时前
Figo几何基础论:基于集合几何化的统一理论框架与哲学意涵——首次提出“几何化诱导的全息原理”
算法·机器学习·概率论·迭代加深
小y要自律18 小时前
11 string容器 - 子串获取
c++·算法·stl
t1987512818 小时前
三相计量芯片RN8302B驱动校正程序设计与实现
算法
好奇龙猫18 小时前
【大学院-筆記試験練習:线性代数和数据结构(17)】
数据结构·学习·线性代数
期末考复习中,蓝桥杯都没时间学了18 小时前
力扣刷题9
算法·leetcode·职场和发展
砚边数影18 小时前
线性回归原理(二):梯度下降算法,Java实现单变量/多变量拟合
java·数据库·算法·线性回归·kingbase·kingbasees·金仓数据库
春日见18 小时前
Docker如何基于脚本拉取镜像,配置环境,尝试编译
运维·驱动开发·算法·docker·容器
csdn_aspnet18 小时前
Java常用算法深度解析:从集合框架到并发编程
java·算法
零基础的修炼19 小时前
位运算---LC268丢失的数字
算法·leetcode·职场和发展