[Leetcode stack and deque sliding window maximum value] (239)

topic

Given an array nums, have a size of k rightmost sliding window moves from the leftmost array to array. You can only see k digits in the sliding window. A time sliding window moves to the right one.

Returns the maximum value in the sliding window.

Example:

输入: 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

Tip:
You can assume that k always effective, in the case of the input array is not empty, 1 ≤ k ≤ size of the input array.

Advanced:
You can linear time complexity of solving this problem it?

answer

Method One: brute force. cur represents a window, a maximum recorded sequentially after the shift. Time complexity of O (n · k), is too slow, the code was more than 30%

Method 2: Top stockpiling large window elements, is the current top of the stack the maximum window, sequentially after the shift, deleting the left, a new element was added, heap deletion operation time complexity of O (log (n)), insertion O ( 1), this method the overall time complexity of O (n · log (k) ).
But! Python does not realize the big top of the heap, with "into the heap, the heap when removed from, all with opposite number" simulated heap big top feasible, that this solved? No! Heapq package can remove the top stack element, but did not provide a way to remove an element of the heap, all the elements first and then find the del delete position in the heap, after del delete, list order is not stored in the stack heap and needs rearrange piles, the time complexity of O (n), so use Python to do it last time complexity of O (n · k), but the hair did not submit to brute speed fast, silent. . .

Method three: deque, the time complexity of O (n)
ideas: sequentially through the elements in the list, cur storage subscript already element in the window, from the backward if the current element is c, then with c and cur elements before the comparison, deleting element cur less than c, and the subscript c cur added in this step to ensure the operation of cur [0] is always element represents the largest window
Note: compare c and cur, must back to front, or part of the sample can not be: [1, 3, 1, 2, 0, 5], k = 3 ..................... .... the video speak from front to back :)

By code is as follows:

from heapq import *


class Solution:

    # 方法一:暴力破解
    # def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
    #     if not nums:
    #         return []
    #     ans = []
    #     cur = []
    #     for x in range(k):
    #         cur.append(nums[x])

    #     ans.append(max(cur))
    #     while x < len(nums)-1:
    #         del cur[0]              # 删除表头
    #         cur.append(nums[x+1])   # 添加到尾
    #         ans.append(max(cur))    # max()的平均时间复杂度是O(n)
    #         x = x+1
    #     return ans

    # 方法二:大顶堆
    # def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
    #     if not nums:
    #         return []
    #     l = []                                  # 预存堆
    #     ans = []
    #     for index, x in enumerate(nums):
    #         if index==0 or len(l)<k:            # 堆还没满,入堆
    #             heappush(l, -x)
    #         else:
    #             ans.append(-l[0])               # 堆顶,最小的,取负数刚好是最大的
    #             del l[l.index(-nums[index-k])]  # 删除窗口左侧第一个
    #             heappush(l, -x)                 # 入堆
    #             heapify(l)                      # 堆貌似乱了......, 重新排列成堆,时间复杂度是O(n)。。。
    #     ans.append(-l[0])
    #     return ans

    # 方法三:双端队列
    def maxSlidingWindow(self, nums, k):
        if not nums:
            return []
        cur = []                                    # 存窗口元素的index,cur[0]位置永远是最大的
        ans = []
        for index, x in enumerate(nums):
            if index >= k and index - k >= cur[0]:  # cur[0]和当前元素的index距离为k,说明cur[0]该从窗口删除了
                cur.pop(0)
            while cur and x >= nums[cur[-1]]:       # 这里,cur要从后往前删小于当前元素的值
                cur.pop()
            cur.append(index)

            if index + 1 >= k:                      # 当前元素位已经走过了窗口距离大小
                ans.append(nums[cur[0]])
        return ans

Guess you like

Origin www.cnblogs.com/ldy-miss/p/11991143.html