diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 56ca7aa7..caa24d8d 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -299,7 +299,7 @@ class Solution { ``` ### Python: - +#### 解法一:使用自定义的单调队列类 ```python from collections import deque @@ -339,30 +339,33 @@ class Solution: return result ``` -#### 新解法:用"堆排序"实现 -* 时间复杂度:`O(n log(n))`, 比`单调队列`解法要慢。 +#### 解法二:直接用单调队列 ```python -import heapq - - +from collections import deque class Solution: def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: - results = [] - num_index_list = [] # 将用“堆排序”对它进行排序,元素为 (num, index) 元组 + max_list = [] # 结果集合 + kept_nums = deque() # 单调队列 for i in range(len(nums)): - # 把 nums[i] 值取负数,最大的就到最小,合乎 Python 堆排序从小到大的规则。 - # 还要把 index (i) 存入,因为通过 i 可知道对应的 num 何时不能再被使用(num 已经处在左侧窗口的更左边) - heapq.heappush(num_index_list, (-nums[i], i)) - # num_index_list[0]是最小值所在 tuple;'<= i - k' 表示 num 已经处在左侧窗口的更左边 - while num_index_list[0][1] <= i - k: # while 表示所有过气 num 都要丢弃 - heapq.heappop(num_index_list) # 丢弃最小值 - - if i >= k - 1: - results.append(-num_index_list[0][0]) # 第一个就是最小值,负最小值就是最大值,加入结果集 + update_kept_nums(kept_nums, nums[i]) # 右侧新元素加入 + + if i >= k and nums[i - k] == kept_nums[0]: # 左侧旧元素如果等于单调队列头元素,需要移除头元素 + kept_nums.popleft() + + if i >= k - 1: + max_list.append(kept_nums[0]) + + return max_list + +def update_kept_nums(kept_nums, num): # num 是新加入的元素 + # 所有小于新元素的队列尾部元素,在新元素出现后,都是没有价值的,都需要被移除 + while kept_nums and num > kept_nums[-1]: + kept_nums.pop() + + kept_nums.append(num) - return results ``` ### Go: