1. 程式人生 > >Leetcode-滑動視窗的最大值_python

Leetcode-滑動視窗的最大值_python

239.給定一個數組 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
注意:

你可以假設 k 總是有效的,1 ≤ k ≤ 輸入陣列的大小,且輸入陣列不為空。

進階:

你能線上性時間複雜度內解決此題嗎?

思路:

1.根據優先佇列的概念,我們假設一個大頂堆,那麼一開始的[1,3,-1],這樣一排列成堆的樣子就是3在最上面,-1在左下角,1在右下角。。下一步就是[3,-1,-3]了,1就要被擠開了,擠開了也不影響什麼,-3再加進來就好了。總之我們需要做的是:(1)維護我們的Heap,也就是刪除離開視窗的元素,加入新的元素。這裡時間複雜度是logK (2)Max->Top,就是讓結果是堆頂的元素。複雜度是O(1),最後整體的複雜度是NLogK。有沒有更好的解法?

2.直接用佇列,而且是雙端佇列,也就是兩邊都能進能出的佇列。首先就是入佇列,每次滑動視窗都把最大值左邊小的數給殺死,也就是出隊,後面再滑動視窗進行維護,這樣相當於就是每一個數走過場,時間複雜度就是O(N*1),比思路1要小。

class Solution:
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        #嚴謹判斷輸入的數字是否合法
        if not nums:return []
        window, res = [], []
        for i, x in enumerate(nums):
            if i>=k and window[0] <= i-k: #視窗滑動時的規律
                window.pop(0)
            while window and nums[window[-1]] <= x: #把最大值左邊的數小的就清除。
                window.pop()
            window.append(i)
            if i >= k-1:
                res.append(nums[window[0]])
        return res