leetcode -- Sliding Window Maximum -- 重点

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

你可能感兴趣的:(LeetCode)