LeetCode 239 Sliding Window Maximum
方法:双端队列
时间复杂度:O(n)
空间复杂度:O(n)
想法:这个题从一开始想的话确实比较难,但我之前已经在LeetCode 1438的题解里写过这种方法了,所以这样倒着复习的话这道题就非常简单了。就是一个双端队列实现动态维护最值,放元素的时候从Last那头放,取最值从First那头取。比方说这道题让我们求滑动窗口的最大值,那肯定得用一个维护最大值的双端队列,那么这个队列从First到Last这个方向一定是单调递减或单调不增(看题目具体情况)。对于这一道题目,队列里面放index也可以,放值也可以。
我们首先考虑放进去的是值,比方说我滑动窗口里有三个3,左边界往右挪的时候,要删掉一个值,万一是3,那么删掉它,我们需要保证队列里面还有两个3,那就是说这种情况我们要维护一个单调不增的序列即可,遇上左边界的值等于队列最值的时候直接大胆删。
如果放进去index可以做吗?这题也可以,因为我如果放index的话,左边界挪的时候,直接检查左边界是不是队列First那端的值就可以了,所以如果用index,这里就既可以用单调递减,也可以单调不增。下面代码只放一个放值的做法,但是改成放index完全没有难度。
代码:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
Deque<Integer> maxQ = new ArrayDeque<>();
int i = 0;
for (; i < k - 1; i++) {
while (!maxQ.isEmpty() && maxQ.peekLast() < nums[i]) {
maxQ.pollLast();
}
maxQ.addLast(nums[i]);
}
int[] res = new int[n - k + 1];
for (; i < n; i++) {
while (!maxQ.isEmpty() && maxQ.peekLast() < nums[i]) {
maxQ.pollLast();
}
maxQ.addLast(nums[i]);
res[i - k + 1] = maxQ.peekFirst();
if (maxQ.peekFirst() == nums[i - k + 1]) {
maxQ.pollFirst();
}
}
return res;
}
}