IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 滑动窗口最大值(力扣) -> 正文阅读

[C++知识库]滑动窗口最大值(力扣)

题目描述:

给你一个整数数组 nums,有一个大小为?k?的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k?个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 ? ? ? ? ? ? ? ?最大值
--------------- ? ? ? ? ? ? ? -----
[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 ? ? ? 5
?1 ?3 ?-1 [-3 ?5 ?3] 6 ?7 ? ? ? 5
?1 ?3 ?-1 ?-3 [5 ?3 ?6] 7 ? ? ? 6
?1 ?3 ?-1 ?-3 ?5 [3 ?6 ?7] ? ? ?7
示例 2:

输入:nums = [1], k = 1
输出:[1]
示例 3:

输入:nums = [1,-1], k = 1
输出:[1,-1]
示例 4:

输入:nums = [9,11], k = 2
输出:[11]
示例 5:

输入:nums = [4,-2], k = 2
输出:[4]

首先我给出思路:

思路: 遍历数组 L R 为滑窗左右边界 只增不减
        双向队列保存当前窗口中最大的值的数组下标 双向队列中的数从大到小排序,
        新进来的数如果大于等于队列中的数 则将这些数弹出 再添加
        当R-L+1=k 时 滑窗大小确定 每次R前进一步L也前进一步 保证此时滑窗中最大值的
        数组下标在[L,R]中,并将当前最大值记录
  举例: nums[1,3,-1,-3,5,3,6,7] k=3
     1:L=0,R=0,队列【0】 R-L+1 < k
            队列代表值【1】
     2: L=0,R=1, 队列【1】 R-L+1 < k
            队列代表值【3】
     解释:当前数为3 队列中的数为【1】 要保证队列中的数从大到小 弹出1 加入3
          但队列中保存的是值对应的数组下标 所以队列为【1】 窗口长度为2 不添加记录
     3: L=0,R=2, 队列【1,2】 R-L+1 = k ,result={3}
            队列代表值【3,-1】
     解释:当前数为-1 队列中的数为【3】 比队列尾值小 直接加入 队列为【3,-1】
          窗口长度为3 添加记录记录为队首元素对应的值 result[0]=3
     4: L=1,R=3, 队列【1,2,3】 R-L+1 = k ,result={3,3}
            队列代表值【3,-1,-3】
     解释:当前数为-3 队列中的数为【3,-1】 比队列尾值小 直接加入 队列为【3,-1,-3】
          窗口长度为4 要保证窗口大小为3 L+1=1 此时队首元素下标为1 没有失效
          添加记录记录为队首元素对应的值 result[1]=3
     5: L=2,R=4, 队列【4】 R-L+1 = k ,result={3,3,5}
            队列代表值【5】
     解释:当前数为5 队列中的数为【3,-1,-3】 保证从大到小 依次弹出添加 队列为【5】
          窗口长度为4 要保证窗口大小为3 L+1=2 此时队首元素下标为4 没有失效
          添加记录记录为队首元素对应的值 result[2]=5
    依次类推 如果队首元素小于L说明此时值失效 需要弹出

?代码还是比较简单的,重要的是理解,链表的一些方法的具体应用。

   public int[] slideWindow(int nums[], int k) {//数组和,窗口的小
        if (nums.length < 2) {
            return nums;//如果数组为空,或者数组大小为一,直接return
        }
        //定义双端队列
        LinkedList<Integer> list = new LinkedList<>();
        //定义存储最大值的数组
        int[] maxNums = new int[nums.length - k + 1];//注意,数组的大小为nums.length-k+1

        //遍历数组
        for (int i = 0; i < nums.length; i++) {
            //检索,如果队列不空,并且要插入的数据大于队列的头数据,就全部出队
            while (!list.isEmpty() && nums[list.peekLast()] <= nums[i]) {
                //全部出队
                list.pollLast();//从队尾位置全部拿出来
            }
            list.addLast(i);//把nums元素的下标,插入到队列的尾部

            //调节窗口的下标,让窗口(在队列中的)的大小保持一定,并且删除队列外的元素
            if(k<=i-list.peek()){
                //检索并删除队列的头
                list.poll();
            }
            //固定窗口后,把每个窗口的最大值,都存储在数组里
            if(i-k+1>=0){
                maxNums[i-k+1]=nums[list.peek()];
            }

        }
        return maxNums;
    }
}

?法二:

我给出不同的解决思路:不用双端队列,而是一般的滑动窗口,

思路是在原始数组的里找到每个窗口中的最大值,并且将每个窗口的最大值,存储在一个集合里。


    private ArrayList<Integer> maxInWindow(int[] a, int size) {
        ArrayList<Integer> list=new ArrayList<Integer>();
        if(size<1||a.length<size) return list;
        int left=0;int right=size-1;//初始的右边界为窗口大小减 1
        while(right<a.length){ //要保证,滚动窗口的右边界始终小于数组大小
            int max=calculate(a,left,right);//计算窗口中的最大值
            list.add(max);//添加最大值
            left++;//窗口向后滚动
            right++;
        }
        return list;
    }

    private int calculate(int[] a, int left, int right) {
        int max=0;
        for(;left<=right;left++){
            if(a[left]>max){
                max=a[left];
            }
        }
        return max;
    }

综上所述:两种方法大同小异,重要的是找到解决思路。

我这里给出测试:

    @Test
    public void test(){
        int a[]=new int[]{1,3,-1,-3,5,3,6,7};
        ArrayList<Integer> in= maxInWindow(a, 3);
        System.out.println("in = " + in);
    }

?

测试代码与预期结果一致。

?

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 11:43:10  更:2021-09-03 11:43:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:18:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码