题目描述:
题目链接:239. 滑动窗口最大值 - 力扣(LeetCode)
题目分析:
思考了半天,大概知道写这个代码应该是个什么思路了。
首先:
首先,这个数组要加窗口,加完窗口之后才开始抽取每一个窗口里边的最大值,而这个窗口最大值在我们的分析和控制下肯定是这个窗口的最左边的位置里边存放的下标对应的值
ok,至于第一个
1.怎么实现加窗口这一步
2.窗口为什么最左边的位置里边存放的下标对应的值就是这里边的最大值
慢慢来分析:
1.窗口,本质上就是一个数组,一个里边只有k个数的数组
2.由于窗口大小不确定,不可能一上来就已经人为的告诉这个数组,你的终点和起点在哪,就算告诉了,你最大值怎么找?再遍历一遍这个窗口数组里边的数字吗?太慢,时间上不一定过得了
3.所以我们最开始,窗口里边肯定啥也没有,从0开始,边移动窗口,边找最大的数字
4.由于我们要控制窗口的大小,所以窗口左右两边的位置要确定,也就是说这个窗口的h位置和t分别指向了原数组的哪里
然后:
1.当窗口里边什么也没有的时候以及什么也不考虑的时候,我们肯定是直接往窗口里边加数字对应的下标,也就是这一句话
deque[++t] =i; //记住窗口里边存的是原数组的下标
2.而且这个下标有一个特点,那就是这个在窗口里边的下标对应的值一定是单调递减的
3.最后加在ans结果数组里的是最前面的那一个数
注意:
其实我们没必要太在意窗口里边是不是已经有了k个数了,因为有些数它是不会用到的,那种逆序数,就比如1 3 -1 ,这里边1是肯定不会被输出出来的,因为有3在,1就不可能作为最大值输出出来,而且1还是先被滑出窗口的,而想让1作为最大值输出来的情况是不是只有前面一两个数都是比1小的数才行,那么如果前面一两个也有比1大的呢,那就可以说明1基本上是没有出头之路,那么1就不用加入窗口中。
i-k+1为此时窗口最左边那个数的下标
有一点我搞错了,就是不一定一定是下一个数比它大才往deque窗口里边记录,而是确实是遇到一个数就往里边记录,如果下一个数比上一个数大,就替换上一个数,下一个数如果没有他大,我们也先加入队列再说,因为后面不知道还有没有比他大的数会超过他
!!!!我上一次写博客没注意到的一点,就是!!!如果队列里边一直大于已经在队列里边存在了的数的话,就要一直把队列里边的数弹出去,然后把它加进去!!!!我就说,怎么感觉原来一直想不通!!!
题解:
class Solution {
public static int N=100007;
public static int[] deque =new int[N];
//双端队列的头和尾位置
public static int h,t ;
public int[] maxSlidingWindow(int[] nums, int k) {
h=0;t=-1;
int m=nums.length-k+1;
int[] ans =new int[m]; //结果数组的长度
int f=0;
for(int i=0;i<nums.length;i++){
//1.挪出去前面的 ---什么时候挪出去--->已经有三个了
if(h<=t && deque[h]<i-k+1) h++; //去除前边的,保证
//i-k+1 前面的过期,挪出去一个数
//2.前面的加进来 ----什么时候挪进来---->想要加进来的数比原来已经有的数大 --->先让他出队
while(h<=t && nums[deque[t]] <=nums[i]) t--; //判断队列是不是空的
//3.无论怎样,然后都要再把那个数加进去 ,因为每次肯定要加一个数进去,
deque[++t] =i; //所以这里可以看出来deque里边放的是下标
//特判 框框满足了就开始往ans结果数组里边放
if(i>=k-1){
ans[f]=nums[deque[h]];
f++;
}
}
return ans;
}
}
解题链接:
【单调队列 滑动窗口最大值【基础算法精讲 27】】https://www.bilibili.com/video/BV1bM411X72E?vd_source=b5fd5146663865201c211e19c2ca9cd2
我能力有限,没听懂的可以在上面那个视频去看一看,讲的还比较清楚