ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

算法练习(六):滑动窗口的最大值

2021-08-24 11:00:38  阅读:103  来源: 互联网

标签:deque 窗口 nums int res 最大值 算法 滑动


题目:给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

输入: 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

  

提示:

你可以假设 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

解题思路:

设窗口区间为 [i, j] ,最大值为 xj 。当窗口向前移动一格,则区间变为[i + 1, j + 1],即添加了nums[j + 1], 删除了nums[i]。

若只向窗口[i, j] 右边添加数字nums[j + 1],则新窗口最大值可以通过一次对比 使用O(1)时间得到, 即:

  xj + 1 = max(xj,nums[j + 1]) 

而由于删除的nums[i]可能恰好是窗口内唯一的最大值xj,因此不能通过以上方法计算xj + 1,而必须使用O(j - i)时间,遍历整个窗口区间获取最大值,即:

  xj+1​=max(nums(i+1),⋯,num(j+1))

根据以上分析,可得 暴力法 的时间复杂度为 O(nk) 。

  • 设数组 nums 的长度为 n,则共有 (n-k+1) 个窗口;
  • 获取每个窗口最大值需线性遍历,时间复杂度为 O(k)。

 

 

 

算法流程:

  1. 初始化: 双端队列 deque ,结果列表 res ,数组长度 n ;
  2. 滑动窗口: 左边界范围 i∈[1−k,n−k] ,右边界范围 j ∈[0,n−1] ;

     1、若 i > 0 且 队首元素 deque[0] == 被删除元素 nums[i - 1] :则队首元素出队;

     2、删除 deque 内所有 < nums[j] 的元素,以保持 deque 递减;
     3、将 nums[j]添加至 deque 尾部;
     4、若已形成窗口(即 i ≥ 0 ):将窗口最大值(即队首元素 deque[0] )添加至列表 res;

 

   3. 返回值: 返回结果列表 res;

package Algriothm;

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;

public class SlidingWindow {


    public static void main(String[] args) {
        System.out.println(Arrays.toString(maxSlidingWindow(new int[]{1, 3, -1, -3, 5, 3, 6, 7}, 3)));;
    }

    public static int[] maxSlidingWindow(int[] nums, int k) {

        if (nums.length == 0 || k == 0) return new int[0];
        Deque<Integer> deque = new LinkedList();
        int[] res = new int[nums.length - k + 1];
        for (int i = 0; i < k; i++) {
            while (!deque.isEmpty() && deque.peekLast() < nums[i]) {
                deque.removeLast();
            }
            deque.addLast(nums[i]);
        }
        res[0] = deque.peekFirst();
        for (int i = k; i < nums.length; i++) {
            if (deque.peekFirst() == nums[i - k]) {
                deque.removeFirst();
            }
            while (!deque.isEmpty() && deque.peekLast() < nums[i]) {
                deque.removeLast();
            }
            deque.addLast(nums[i]);
            res[i - k + 1] = deque.peekFirst();
        }
        return res;
    }
    
}

  

标签:deque,窗口,nums,int,res,最大值,算法,滑动
来源: https://www.cnblogs.com/yssd/p/15179323.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有