题目描述
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 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
思路
这道题暴力解法大部分人都会,遍历每一个起点,在每个窗口内寻求最大值就好了,但时间复杂度达到了O(n*k),在leetcode上提交会运行超时,如何降低时间复杂度呢?
有没有这样的一种数据结构?每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。这样我们就能在O(n)的时间复杂度内得出结果。
事实上是没有的! 我们需要自己实现这么个数据结构,我们称之为单调队列。
如何做到呢?
我们在设计单调队列的时候,pop和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
保持如上规则,每次窗口移动的时候,队列里面始终维持单调递减的状态,只要调用que.front()就可以返回当前窗口的最大值。
解法
C++版本
Java版本