Leetcode刷題:劍指offer【面試題59-Ⅰ 滑動窗口的最大值】

【面試題59-Ⅰ 滑動窗口的最大值】

面試題59-Ⅰ:滑動窗口的最大值:給定一個數組 nums 和滑動窗口的大小 k,請找出所有滑動窗口裏的最大值。

思路一:暴力法。從 0 位置遍歷數組,到 n-k+1 位置結束,每次獲取滑動窗口中最大的數 append 到 res 數組中。

時間複雜度O(nk)O(nk),除了滑動窗口,每次在窗口內尋找最大值也需要時間消耗,對於大小爲 k 的窗口,查找最大值的花費就是 O(k)O(k)
空間複雜度O(n)O(n),最差情況下,滑動窗口大小爲 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

思路二:爲了將查找最大值的時間複雜度由 O(k)O(k) 降爲 O(1)O(1),可以使用類似單調棧的思想,讓最大值保持在頂端。

滑動窗口實際是不斷在右邊添加新元素的同時刪除左邊的元素,所以用 雙端隊列 實現:

  • 雙端隊列內的元素非嚴格遞減,即向右添加新的元素時,將隊列內所有小於該元素的元素都刪除
  • 若滿足非嚴格遞減,只需要將當前窗口外的元素從隊列中刪除,即如果隊首元素和被刪除的元素相等,則將隊首元素出隊

時間複雜度O(n)O(n)
空間複雜度O(n)O(n)

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

代碼來源:mian-shi-ti-59-i-hua-dong-chuang-kou-de-zui-da-1-6

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章