描述
给出一个可能包含重复的整数数组,和一个大小为 k 的滑动窗口, 从左到右在数组中滑动这个窗口,找到数组中每个窗口内的最大值。
您在真实的面试中是否遇到过这个题? 是
样例
给出数组 [1,2,7,7,8]
, 滑动窗口大小为 k = 3
. 返回 [7,7,8]
.
解释:
最开始,窗口的状态如下:
[|1, 2 ,7| ,7 , 8]
, 最大值为 7
;
然后窗口向右移动一位:
[1, |2, 7, 7|, 8]
, 最大值为 7
;
最后窗口再向右移动一位:
[1, 2, |7, 7, 8|]
, 最大值为 8
.
挑战
O(n)时间,O(k)的额外空间
实现代码:
思路:
method 1:
定义一个双端队列,用来存储滑动窗口中的值的下标,其中最大值必须放在队首。
如果qmax中有值,则从后往前比较,如果nums[qmax[-1]] <= nums[i],则弹出小的值,保证了qmax的顺序为递减,队首是最大值。
如果 qmax[0] 即队首 小于等于 i-k,即滑动窗口已经滑过qmax[0]所在范围,必须弹出了。
如果 i< k-1,则数组大小小于滑动窗大小,略过。
将qmax[0]的值加入res中。
method 2:
利用max函数, 从头开始滑动,记录滑动窗内最大值。
如果num[i-1]等于maxNum, 则证明滑动窗已经滑过了最大值所在位置,需要更新最大值。
如果num[i + k -1] 大于等于maxNum,则证明滑动窗的最后一位数大于最大值,则更新最大值。
否则直接将maxNum加入res,不做比较。
class Solution: """ @param: nums: A list of integers @param: k: An integer @return: The maximum number inside the window at each moving """ ''' def maxSlidingWindow(self, nums, k): # write your code here n = len(nums) if n == 0 or k<1 or n < k: return [] #定义一个双端队列 qmax = [] res = [0]*(n-k+1) index = 0 for i in range(n): while qmax and nums[qmax[-1]] <= nums[i]: qmax.pop() qmax.append(i) if qmax[0] == i-k: qmax.pop(0) if i >= k-1: res[index] = nums[qmax[0]] index+=1 return res ''' ''' def maxSlidingWindow(self, nums, k): # write your code here n = len(nums) if n == 0 or k<1 or n < k: return [] #定义一个双端队列 qmax = [] res = [] for i in range(n): while qmax and nums[qmax[-1]] <= nums[i]: qmax.pop() qmax.append(i) if i < k-1: continue while qmax and qmax[0] <= i - k: qmax.pop(0) res.append(nums[qmax[0]]) return res ''' def maxSlidingWindow(self, nums, k): # write your code here n = len(nums) if n == 0 or k < 1: return [] if n <= k: return [max(nums)] res = [] maxNum = max(nums[:k]) res.append(maxNum) for i in range(1, n - k + 1): if nums[i - 1] == maxNum: maxNum = max(nums[i:i + k]) res.append(maxNum) elif nums[i + k - 1] >= maxNum: maxNum = nums[i + k - 1] res.append(maxNum) else: res.append(maxNum) return res