362. 滑動視窗的最大值(單調佇列)
阿新 • • 發佈:2020-07-15
362.滑動視窗的最大值
中文English給出一個可能包含重複的整數陣列,和一個大小為k的滑動視窗, 從左到右在陣列中滑動這個視窗,找到陣列中每個視窗內的最大值。
樣例
樣例 1:
輸入:
[1,2,7,7,8]
3
輸出:
[7,7,8]
解釋:
最開始,視窗的狀態如下:`[|1, 2 ,7| ,7 , 8]`, 最大值為 `7`;
然後視窗向右移動一位:`[1, |2, 7, 7|, 8]`, 最大值為 `7`;
最後視窗再向右移動一位:`[1, 2, |7, 7, 8|]`, 最大值為 `8`.
樣例 2:
輸入: [1,2,3,1,2,3] 5 輸出: [3,3] 解釋: 最開始,視窗的狀態如下: `[|1,2,3,1,2 | ,3]` , 最大值為`3`; 然後視窗向右移動一位.`[1, |2,3,1,2,3]`, 最大值為 `3`;
挑戰
O(n)時間,O(k)的額外空間
堆實現(heapq)
import heapq class Solution: """ @param nums: A list of integers. @param k: An integer @return: The maximum number inside the window at each moving. """ def maxSlidingWindow(self, nums, k): # write your code here #堆實現if len(nums) < k or not nums: return nums #初始化 length = len(nums) result = [] for i in range(length - k + 1): temp_array = nums[i: i + k] pop_num = temp_array[0] heapq._heapify_max(temp_array) result.append(temp_array[0]) temp_array.remove(pop_num) return result
注:堆方法時間複雜度問題,未通過
雙端佇列(單調佇列)
from collections import deque class Solution: """ @param nums: A list of integers. @param k: An integer @return: The maximum number inside the window at each moving. """ def maxSlidingWindow(self, nums, k): # write your code here if not nums: return [] #雙端佇列(保持單調遞減) queue = deque([]) length = len(nums) result = [] count = 0 for i in range(length): #如果是當前元素 > 隊尾的話,需要pop掉隊尾元素,一直到滿足當前queue[-1] >= 當前元素 while count != 0 and queue[-1][0] < nums[i]: queue.pop() count -= 1 #如果是長度大於等於k的話,需要移除前面的元素,後面保持k個數量即可 #注意,所謂的視窗移動,指的時nums的視窗移動,不是指的是queue保持在k長度,指的是nums的保持k長度 if count != 0 and i - queue[0][1] >= k: queue.popleft() count -= 1 queue.append([nums[i], i]) count += 1 #開始往result裡面加的話,此時則說明i是大於等於k - 1 ,隊首即為最大的元素 if (i >= k - 1): result.append(queue[0][0]) return result
下面版本也可以
class Solution: """ @param nums: A list of integers. @param k: An integer @return: The maximum number inside the window at each moving. """ def maxSlidingWindow(self, nums, k): # write your code here if not nums: return [] #雙端佇列 queue = [] length = len(nums) result = [] count = 0 for i in range(length): #如果是當前元素 > 隊尾的話,需要pop掉隊尾元素,一直到滿足當前queue[-1] >= 當前元素 while count != 0 and queue[-1][0] < nums[i]: queue.pop() count -= 1 #如果是長度大於等於k的話,需要移除前面的元素,後面保持k個數量即可 #注意,所謂的視窗移動,指的時nums的視窗移動,不是指的是queue保持在k長度,指的是nums的保持k長度 if count != 0 and i - queue[0][1] >= k: queue.pop(0) count -= 1 queue.append([nums[i], i]) count += 1 #開始往result裡面加的話,此時則說明i是大於等於k - 1 ,隊首即為最大的元素 if (i >= k - 1): result.append(queue[0][0]) return result