【面試題59-Ⅰ 滑動窗口的最大值】
面試題59-Ⅰ:滑動窗口的最大值:給定一個數組 nums 和滑動窗口的大小 k,請找出所有滑動窗口裏的最大值。
思路一:暴力法。從 0
位置遍歷數組,到 n-k+1
位置結束,每次獲取滑動窗口中最大的數 append 到 res 數組中。
時間複雜度:,除了滑動窗口,每次在窗口內尋找最大值也需要時間消耗,對於大小爲 k 的窗口,查找最大值的花費就是
空間複雜度:,最差情況下,滑動窗口大小爲 1,此時 res 數組和原數組一摸一樣
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums: return []
n = len(nums)
res = []
for i in range(n-k+1):
res.append(max(nums[i:i+k]))
return res
思路二:爲了將查找最大值的時間複雜度由 降爲 ,可以使用類似單調棧的思想,讓最大值保持在頂端。
滑動窗口實際是不斷在右邊添加新元素的同時刪除左邊的元素,所以用 雙端隊列 實現:
- 雙端隊列內的元素非嚴格遞減,即向右添加新的元素時,將隊列內所有小於該元素的元素都刪除
- 若滿足非嚴格遞減,只需要將當前窗口外的元素從隊列中刪除,即如果隊首元素和被刪除的元素相等,則將隊首元素出隊
時間複雜度:
空間複雜度:
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums or k == 0: return []
deque = collections.deque()
# 未形成窗口
for i in range(k):
while deque and deque[-1] < nums[i]: deque.pop() # 保證非嚴格遞減
deque.append(nums[i])
res = [deque[0]]
# 形成窗口後
for i in range(k, len(nums)):
if deque[0] == nums[i - k]: deque.popleft()
while deque and deque[-1] < nums[i]: deque.pop()
deque.append(nums[i])
res.append(deque[0])
return res