diff --git a/notes/59. 滑动窗口的最大值.md b/notes/59. 滑动窗口的最大值.md index 95b03876..3161e28e 100644 --- a/notes/59. 滑动窗口的最大值.md +++ b/notes/59. 滑动窗口的最大值.md @@ -14,9 +14,11 @@ ## 解题思路 +### 大顶堆 + 维护一个大小为窗口大小的大顶堆,堆顶元素即为当前窗口的最大值。 -假设窗口的大小为 M,数组的长度为 N。在窗口向右移动时,需要先在堆中删除离开窗口的元素,并将新到达的元素添加到堆中,这两个操作的时间复杂度都为 log2M,因此算法的时间复杂度为 O(Nlog2M),空间复杂度为 O(M)。 +假设窗口的大小为 M,数组的长度为 N。在窗口向右移动时,需要先在堆中删除离开窗口的元素,并将新到达的元素添加到堆中。添加的时间复杂度为 O(logM),但 PriorityQueue.remove(Object) 要先线性查找这个元素,时间复杂度为 O(M),因此算法的时间复杂度为 O(NM),空间复杂度为 O(M),N 和 M 都很大时会超时。 ```java public int[] maxAltitude(int[] heights, int limit) { @@ -38,3 +40,34 @@ public int[] maxAltitude(int[] heights, int limit) { return ret; } ``` + +### 单调队列 + +用双端队列保存窗口中有可能成为最大值的元素的下标,并让它们对应的值从队头到队尾递减,队头就是当前窗口的最大值: + +- 新元素入队前,从队尾删除所有不大于它的元素:它们比新元素先离开窗口,值又不比它大,以后不可能成为最大值; +- 队头的下标离开窗口时,从队头删除。 + +每个下标最多入队、出队各一次,时间复杂度为 O(N),空间复杂度为 O(M)。以 {2, 3, 4, 2, 6, 2, 5, 1}、窗口大小 3 为例: + +