Skip to content

239 Sliding Window Maximum

Approach 1: Brute Force

Brute force solution would be slicing every window and take the maximum of each window. The time complexity would be O(n*k) where n is the length of the array and k is the window size.

Approach 2: Monotonic Queue

既然是求sliding window最大值,我们可以用一个monotonically decreasing的queue来维护window内的最大值和单调性.

queue: storing the "index" for an decreasing monotonic queue. 
res: 记录max index for monotonic queue

可以分成两个部分:

  • 初始化第一个window
    • 如果新元素比queue中的最后一个元素大,pop掉最后一个元素,直到queue被清空或者新元素比queue中的最后一个元素小
    • 记录queue中的第一个元素到res中, 此时res长度为1
  • 从第2个 to 第(n-k+1)个 window
    • 如果queue中的第一个元素已经离开当前window, pop掉第一个元素
    • 如果新元素比queue中的最后一个元素大,pop掉最后一个元素,直到queue被清空或者新元素比queue中的最后一个元素小
    • 把新元素的index加入queue
    • 记录queue中的第一个元素到res中, res长度 +1 直到res长度为n-k+1

Note

  • time complexity: \(O(n)\) 看上去像是for + while loop, 但实际上worst case scenario是每个元素都进出queue一次,所以是\(O(2n) \approx O(n)\)
  • space complexity: \(O(k)\), queue的最大长度为k

Code Implementation

from collections import deque
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        # 求每一个window中的最大值,所组成的Array.
        queue = deque()
        res = []
        n = len(nums)

        # initialize the initial monotonic queue (in the first window of size k)
        for i in range(k):
            # pop 队列中小于新元素nums[i]的值, 直到结束
            while queue and nums[i] >= nums[queue[-1]]:
                queue.pop()
            queue.append(i)

        res.append(nums[queue[0]])

        for i in range(k,n):
            # 比较queue最左边值是否已经离开window
            if queue and queue[0] == i-k:
                queue.popleft()
            while queue and nums[i] >= nums[queue[-1]]:
                queue.pop()
            # enque
            queue.append(i)
            res.append(nums[queue[0]])

        return res