文章目录
- 题目描述
- 思路 && 代码
- 1. 暴力法 O(n2n^2n2) && O(1)
- 2. 单调队列辅助 O(n) && O(n)
- 二刷
打卡第十天~
题目描述
- 久违的滑动窗口题!
思路 && 代码
1. 暴力法 O(n2n^2n2) && O(1)
- 老规矩,先来个暴力法熟悉一下题目~
- 出乎意料没有超时…不过我们还是需要寻找更优的做法!
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if(nums.length == 0) {return new int[]{};}int[] res = new int[nums.length - k + 1];// 暴力for(int i = 0; i < res.length; i++) {int max = nums[i];for(int j = 0; j < k; j++) {max = Math.max(max, nums[i + j]);}res[i] = max; } return res;}
}
2. 单调队列辅助 O(n) && O(n)
- 空间换时间!
- 利用一个单调递减的队列,始终把当前滑动窗口最大值置于队头
- 更新判断一:当前队头是否已经脱离滑动窗口。(我觉得这块具体代码不太好想到)
- 更新判断二:加入当前数组元素,是否会改变队列递减特性
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if(nums.length == 0) {return new int[]{};}// 队列头:记录滑动窗口最大值Deque<Integer> deque = new LinkedList<>();int[] res = new int[nums.length - k + 1];for(int i = 0, windowTail = 1 - k; i < nums.length; i++, windowTail++) {// 更新一:去掉前一个窗口尾值if(windowTail > 0 && deque.peekFirst() == nums[windowTail - 1]) {deque.removeFirst();}// 更新二:保持递减while(!deque.isEmpty() && deque.peekLast() < nums[i]) {deque.removeLast();}deque.addLast(nums[i]);// 记录窗口最大值if(windowTail >= 0) {// 窗户尾值,同时也是 res 的对应下标res[windowTail] = deque.peekFirst();}}return res;}
}/*1. 采用单调队列2. 主要是 队列头 的处理3. 通过维护 windowTail 来维护队列(重要)
*/
二刷
- 单调队列,找最大值,则需要单调减(队头为最大)
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if(nums.length == 0) {return new int[]{};}int[] ans = new int[nums.length - k + 1];Deque<Integer> queue = new ArrayDeque<>();for(int i = 0, windowTail = 1 - k; i < nums.length; i++, windowTail++) {// step1: 去掉上一个窗口尾值if(windowTail > 0 && queue.element() == nums[windowTail - 1]) {queue.poll();}// step2: 保持递减(注意,没有按照正常的队列顺序,是从后面开始处理的while(!queue.isEmpty() && nums[i] > queue.getLast()) {queue.removeLast();}queue.offer(nums[i]);if(windowTail >= 0) {ans[windowTail] = queue.element();}}return ans;}
}