【leetcode239】滑動視窗最大值
題目:給定乙個陣列 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 ≤ 輸入陣列的大小
高階:
思路:一般情況下使用暴力法,時間複雜度為o(nk),之前想過用棧,但是用棧複雜度最糟糕也是o(nk)當然比暴力法稍微好一些,最後決定用雙端佇列,容易處理滑動視窗問題,因為在隊列為體重視窗左面和右面的值pop後複雜度都是o(1)。因此首先設定乙個函式clear_deque,這個函式實現兩個重要功能(1、控制滑動視窗長度2、使得佇列deque中隊頭儲存的是k個元素中的最大值,也就是如果來了乙個元素,裡面所有比該元素小的元素都pop出去,那麼剩下的就是最大值(隊頭))。
**如下:
from collections import deque#問題的關鍵是使用雙端佇列,要求兩頭都能pop資料且複雜度為o(1)
class solution:
def maxslidingwindow(self, nums: 'list[int]', k: 'int') -> 'list[int]':
# base cases
n = len(nums)
if n * k == 0:
return
if k == 1:
return nums
def clean_deque(i):
# remove indexes of elements not from sliding window
# 滑動視窗範圍 用下標來實現
if deq and deq[0] == i - k:
deq.popleft() #丟擲佇列的第乙個元素也就是deq[0]
# remove from deq indexes of all elements
# which are smaller than current element nums[i]
# 找最大值,即把比該值小的全部pop掉
while deq and nums[i] >= nums[deq[-1]]:
deq.pop()
# init deque and output
deq = deque()
max_idx = 0
# 前k個值比較特殊,為什麼要把前k個數單獨拎出來,經過分析一共要輸出n-k+1個元素
# 裡面的1就是nums前k元素的最大值
for i in range(k):
clean_deque(i)
# compute max in nums[:k]
# if nums[i] > nums[max_idx]:
# max_idx = i
output = [nums[deq[0]]]
# build output
for i in range(k, n):
clean_deque(i)
return output
leetcode 佇列習題
最近的請求次數 寫乙個 recentcounter 類來計算最近的請求。它只有乙個方法 ping int t 其中 t 代表以毫秒為單位的某個時間。返回從 3000 毫秒前到現在的 ping 數。任何處於 t 3000,t 時間範圍之內的 ping 都將會被計算在內,包括當前 指 t 時刻 的 pi...
leetcode 棧和佇列
20.有效的括號 給定乙個只包括 的字串,判斷字串是否有效。有效字串需滿足 左括號必須用相同型別的右括號閉合。左括號必須以正確的順序閉合。注意空字串可被認為是有效字串。示例 1 輸入 輸出 true 示例 2 輸入 輸出 true 示例 3 輸入 輸出 false 示例 4 輸入 輸出 false ...
leetcode 佇列習題02
設計迴圈佇列 設計你的迴圈佇列實現。迴圈佇列是一種線性資料結構,其操作表現基於 fifo 先進先出 原則並且隊尾被連線在隊首之後以形成乙個迴圈。它也被稱為 環形緩衝器 迴圈佇列的乙個好處是我們可以利用這個佇列之前用過的空間。在乙個普通佇列裡,一旦乙個佇列滿了,我們就不能插入下乙個元素,即使在佇列前面...