https://leetcode.com/problems/sliding-window-maximum/
思路见code,参考http://www.jianshu.com/p/7662caf4f39c
http://bookshadow.com/weblog/2015/07/18/leetcode-sliding-window-maximum/
为什么要用deque呢?
这里是滑动窗口,每次滑动,都会有值从右边进,然后又有值从左边出。所以用双向队列就很好。维护队头元素为当前窗口的最大值.因为向右滑动的时候,要从左边remove一个元素,如果这个元素是上一个window的最大值,那么就要更新这个最大值,这个新的最大值肯定出现在旧的最大值的后面,所以,这里用deque,队头为最大元素,下一个元素为这个最大元素后面的最大元素。。。
思路:
遍历数组nums,使用双端队列deque维护滑动窗口内有可能成为最大值元素的数组下标
由于数组中的每一个元素至多只会入队、出队一次,因此均摊时间复杂度为O(n)
记当前下标为i,则滑动窗口的有效下标范围为[i - (k - 1), i]
若deque中的元素下标< i - (k - 1),则将其从队头弹出,deque中的元素按照下标递增顺序从队尾入队。
这样就确保deque中的数组下标范围为[i - (k - 1), i],满足滑动窗口的要求。
当下标i从队尾入队时,顺次弹出队列尾部不大于nums[i]的数组下标(这些被弹出的元素由于新元素的加入而变得没有意义)
deque的队头元素即为当前滑动窗口的最大值
这里deque就是维护一个区间内第一大,第二大,。。。的结构,最大的放在队头
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
res = []
d = collections.deque()
for i in range(len(nums)):
while d and d[-1] < nums[i]:#等于可以跳出了
d.pop()
d.append(nums[i])
if i > k - 1 and d[0] == nums[i - k]:
'''
这里i > k - 1,就是第一个windows已经建好了,开始滑动。d[0] == nums[i - k], 本来的windows index是从[i - (k-1), i],i现在往前走了一步,现在区间变成了[i-k, i],window长度为k+1, 要popleft掉第一个i-k元素。新的队头元素就是新的max
'''
d.popleft()
if i >= k - 1:#窗口开始滑动之后deque的第一个值就是结果。
res.append(d[0])
return res