Leetcode239 滑动窗口
这题真的好难啃第一遍读,已经废掉了脑细胞
今天就先跟着视频及答案理解敲一遍,写了思路如下:
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
//leetcode submit region begin(Prohibit modification and deletion)
class Myqueue{
Deque<Integer> deque = new LinkedList<>();
void poll(int val){
//______________________
//_出口_____________入口__
if(!deque.isEmpty() && val==deque.peek()){
deque.poll();
//如果是等于最大的那个元素即出口元素,直接出队
//否则不操作
}
}
void add(int val){//保持单调递减
//______________________
//_出口_____________入口__
//添加元素>入口元素;弹出直到小于等于呈单调递减
while (!deque.isEmpty()&& val>deque.getLast()){
deque.removeLast();//删除出口处元素
}
deque.add(val);
}
int peek(){
return deque.peek();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//剪枝
if(nums.length == 1){
return nums;
}
//创建结果数组
int[] res = new int[nums.length-k+1];
int resindex = 0;
Myqueue myqueue = new Myqueue();
for (int i = 0; i < k; i++) {
myqueue.add(nums[i]);
}
res[resindex] = myqueue.peek();
resindex++;
for (int i = k; i < nums.length; i++) {
myqueue.poll(nums[i-k]);
myqueue.add(nums[i]);
res[resindex] = myqueue.peek();
resindex++;
}
return res;
}
}
明天重新看一编应该会有新收获吧
早晨起来把 这一题又写了一次
import java.util.Deque;
import java.util.LinkedList;
//leetcode submit region begin(Prohibit modification and deletion)
class MonQueue{
Deque<Integer> myqueue = new LinkedList<>();
void pop(int val){
if (!myqueue.isEmpty() && myqueue.peek()==val){
myqueue.pop();//pop是出口处
//myqueue.peek() 出口位置
}
}
void add(int val){
//getLast(),removeLast() 都是在入口处查看数值及弹出元素
//是为了维持队列的单调性,必须为单调递减,所在添加元素时,如果前一个<val ,就需要弹出 再判断 直到元素>val
while(!myqueue.isEmpty() && myqueue.getLast()<val){
myqueue.removeLast();
}
myqueue.add(val);
}
int front(){
//获取窗口最大元素并返回,即为出口处元素
return myqueue.peek();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 1){
return nums;
}
int reslength = nums.length-k+1;
int[] res = new int[reslength];
int resindex = 0;
//创建单调队列
MonQueue monQueue = new MonQueue();
//初始化滑动窗口 并将对应的最大值加入到res
for(int i = 0;i < k; i++){
monQueue.add(nums[i]);
}
res[resindex++] = monQueue.front();
//依次循环滑动窗口
for(int i = k;i<nums.length;i++){
//pop对应索引应该从0 - nums.length-k
monQueue.pop(nums[i-k]);
monQueue.add(nums[i]);
res[resindex++] = monQueue.front();
}
return res;
}
}
//leetcode submit region end(Prohibit modification and deletion)
实现思路是:通过使用自己创建单调队列实现滑动窗口获取最大值
1.单调队列类: 包含三个成员函数
- pop(val) --- val滑动窗口出口位置要输出元素值
- 如果deque出口位置值与 val 相关且不为空 就弹出
- add(val) --- val滑动窗口入口位置要添加元素值
- 使用循环实现 队列入口位置值 < val ----如不符就弹出出口处值直到符合
- 再进行添加
- front() --- 获得出口位置值即窗口最大值
2.主函数内:
- 剪枝: 如果队列只有一个数 直接返回对应值 退出
- 创建结果数组 长度 数组长度-滑动窗口长度+1
- 创建引入 单调队列进行操作
- 初始化 添加前k个元素 (add);将front 加入结果数组,索引自增
- for 实现滑动: 执行 pop add front ;对应的操作元素 分别是 num[i-k] num[i] 无
- resturn res;