剑指 Offer 59 - I. 滑动窗口的最大值
题目描述
给定一个数组nums和滑动窗口的大小k,请找出所有滑动窗口里的最大值。
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7🔗题目链接:https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof
思路
单调队列,维护一个队列使其队头元素为当前滑动窗口的最大值,具体操作如下:
- 将进入窗口的新元素与队尾元素进行比较,新元素大于队尾元素就将队尾元素出队,否则就入队新元素,如窗口元素[1,3,-1],则对应的队列元素为[3,,-1];
-
每次移动窗口时先判断移出窗口的元素,即窗口最左端的元素是否为队头元素,是就将其出队,再将新的元素入队到合适的位置,接着取队头元素存入结果数组,作为当前窗口的最大值。
代码实现
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { if(nums.length == 0 || k == 0){ return new int[0]; } int[] res = new int[nums.length - k + 1]; Deque<Integer> deque = new LinkedList<>(); //维护队头元素为当前队列及滑动窗口中的最大值 for(int i = 0; i < k; i++){ //先形成规定的滑动窗口 while(!deque.isEmpty() && deque.peekLast() < nums[i]){ //若当前元素大于队尾元素,就将队尾元素出队 deque.removeLast(); } deque.addLast(nums[i]); //将当前元素进行入队 } res[0] = deque.peekFirst(); for(int i = k; i < nums.length; i++){ if(deque.peekFirst() == nums[i - k]){ //若队头元素等于窗口最左端的值,即原窗口的最大值要被移出了, //则需要先将其出队,因为它已经不是本次窗口的最大值了 deque.removeFirst(); } //移除队列中小于窗口新元素的值,将新元素入队 while(!deque.isEmpty() && deque.peekLast() < nums[i]){ deque.removeLast(); } deque.addLast(nums[i]); //取当前队列的队头元素加入结果数组 res[i - k + 1] = deque.peekFirst(); } return res; } }
剑指 Offer 59 - II. 队列的最大值
题目描述
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
🔗题目链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof
若队列为空,pop_front 和 max_value 需要返回 -1
🔗题目链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof
思路
单调队列,通过一个辅助队列维护队列的最大值,具体操作与上题类似。
代码实现
class MaxQueue { Deque<Integer> deque; Deque<Integer> subDeque; //辅助队列 public MaxQueue() { deque = new LinkedList<>(); subDeque = new LinkedList<>(); } public int max_value() { if(deque.isEmpty()){ return -1; } return subDeque.peekFirst(); //返回队头元素 } public void push_back(int value) { deque.offer(value); //将辅助队列中队尾元素与value比较,小于的移出队列,直到队列为空或遇到大于等于value的元素 while(!subDeque.isEmpty() && subDeque.peekLast() < value){ subDeque.removeLast(); } subDeque.offer(value); //接着将该值入队 } public int pop_front() { if(deque.isEmpty()){ return -1; } int value = deque.poll(); if(value == subDeque.peekFirst()){ //当出队元素与辅助队列队头元素相等时才出队 subDeque.poll(); } return value; } } /** * Your MaxQueue object will be instantiated and called as such: * MaxQueue obj = new MaxQueue(); * int param_1 = obj.max_value(); * obj.push_back(value); * int param_3 = obj.pop_front(); */