239. 滑动窗口最大值
https://leetcode-cn.com/problems/sliding-window-maximum/
题目描述
方法 1:暴力法(TLE)
思路
直觉想法,当然是在滑动窗口每次滑动时都遍历窗口找到最大值,果不其然超时了 ╮(╯_╰)╭
49 / 59 个通过测试用例
复杂度分析
时间复杂度:$O((N-k)*k)$,N 是数组长度。
空间复杂度:$O(1)$。
代码
JavaScript Code
方法 2:大顶堆(TLE)
思路
要找最大值,自然而然就能想到堆了。
但如果直接每个滑动窗口都建一个堆的话,
时间复杂度是 $O(klogk*(N-k))$:
其中建堆的时间是 $O(klogk)$。
一共有 $N-k+1$ 个滑动窗口。
空间复杂度是 $O(k)$,堆的大小。
这样时间复杂度还是太高了,会超时(49 / 59 个通过测试用例)。
优化
我们要记住固定长度滑动窗口的特点,就是 每次滑动变动的只有头尾两个元素。
如果我们能在窗口滑动时用新元素替换旧元素,再对堆进行 heapify 操作,这样时间复杂度就变成了:
建堆时间复杂度是 $O(klogk)$。
滑动窗口滑动时,替换元素的时间是 $O(k+logk)$,
其中找到旧元素的时间是 $O(k)$
heapify 的时间是 $O(logk)$
一共有 $N-k+1$ 个滑动窗口,所以总的时间复杂度是 $O(klogk + (N-k)(logk + k))$
也就是 $O(N*k)$ 吧 (⓿_⓿) 大概可以这样约掉...忽略掉其中较小的数
原以为能 AC 的,大意了,还是 TLE。
JavaScript: 52 / 59 个通过测试用例 Python: 49 / 59 个通过测试用例
复杂度分析
时间复杂度:$O(N*k)$。
空间复杂度:$O(k)$。
代码
Python Code
JavaScript Code
方法 3:平衡二叉搜索树
思路
滑动窗口的大小是 k,我们要找出 k 个数字中的最大值。
窗口每次滑动时变化的只有头尾两个数字。
基于以上两点,我们可以考虑用一个数据结构来存这 k 个数字,每次窗口滑动时,用 nums[r+1] 替换掉 nums[l],然后再返回 k 个数字中的最大值。
因此我们需要的是一个可以快速找到 nums[l],还能快速找到最大值,也就是,能 快速查找值 的数据结构。就是你啦!二叉搜索树!
不过,二叉搜索树有可能会退化成链表,搜索时间变成 $O(N)$,而平衡二叉搜索树,也就是 AVL 树,作为升级版的二叉搜索树,它的搜索时间永远是 $O(logN)$,所以我们可以用 AVL 树。
由于我还没有写过 AVL 树,这里就偷懒不写啦。(。_。) 不知道会不会超时。
复杂度分析
时间复杂度:$O((N-k)*logk)$,N 是数组长度,一共有 $N-k+1$ 个滑动窗口,$logk$ 是向 AVL 树插入和查询值的时间。
空间复杂度:$O(k)$,AVL 树的大小。
代码(TODO)
JavaScript Code
方法 4:deque
思路
直觉解法全都超时了,看来虽然题目说进阶是线性时间,但我看它根本就是要求线性时间!
题目给了提示说可以用 deque。没力气写太多,直接看代码注释吧 ( ╯□╰ )。
复杂度分析
时间复杂度:$O(N)$,N 是数组长度,每个数字最多入列出列一次。
空间复杂度:$O(k)$,deque 的空间。
代码
JavaScript Code
单调队列 @feiker
JavaScript Code
Last updated
Was this helpful?