Sliding Window Maximum
题目描述
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position Max
[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
Therefore, return the max sliding window as [3,3,5,5,6,7].
Follow up:
Could you solve it in linear time?
解题方法
brute force
维护window,每次遍历找最大值,O(nk)
max heap
维护max heap, O(nlogk)
deque
我们可以从这个window移动的过程找出规律,因为window移动时总是去掉开头 的数字,有点像queue,而我们每次又要在末尾加上新的数字,所以这种首尾都要 操作的数据结构应该用deque.
那么如何找最大值呢?通过观察可以发现,如果后面出现了一个大的数,那么它 前面比它小的数其实我们就不用再记录了,因为不会用它们作为最大值,将它们 pop出去的时候也不影响当前的最大值。
所以每次遇到新的值时,我们就将deque后面比它小的数都pop出去。这样deque[0] 永远保持的是当前window里的最大值。
Solution
from collections import deque
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
if not nums:
return []
result = []
dq = deque()
for idx, num in enumerate(nums):
while dq and nums[dq[-1]] < num: # pop smaller elements
dq.pop()
dq.append(idx) # save index in the deque
if idx - k == dq[0]: # if idx-k is the first element's index, should remove
dq.popleft()
if idx >= k - 1: # add each window's max
result.append(nums[dq[0]])
return result