【题目描述 】
AcWing 79. 滑动窗口的最大值
【思路】
朴素做法
/**
左右指针l、r维护一个大小为k的窗口
该窗口的最大值 则为区间[l,r]的最大值
*/
class Solution {
public int[] maxInWindows(int[] nums, int k) {
int n = nums.length;
int ans[] = new int [n - k + 1];
for(int l = 0, r = l + k - 1; l + k <= n; l ++, r ++){
int max = nums[l];
for(int i = l; i <= r; i ++)
max = nums[i] > max ? nums[i] : max;
ans[l] = max;
}
return ans;
}
}
单调队列
1、用队列维护窗口最大值的下标,该队列存储的值对应数组值单调递减,队头存储滑动窗口最大值下标。
2、窗口区间为[l, r],则如果队列中队头元素下标q.peekFirst() , q.peekFirst() < l了 ,则该数滑出窗口了,需将该数弹出。
3、数组指针r向右移动,如果队列为空,则将数组下标加入队列,如果不为空,判断该队列的队头有没有滑出窗口。滑出则弹出队首。然后将该数组下标插入合适位置(要使得该队列为单调递减)。
class Solution {
public int[] maxInWindows(int[] nums, int k) {
int n = nums.length;
int []ans = new int[n - k + 1]; //n个数,窗口大小为k则窗口数为n - k + 1
if(k == 0) return ans;
//双向队列
ArrayDeque<Integer> q = new ArrayDeque<>();
int index = 0;
for(int r = 0; r < n; r ++)//窗口右指针
{
int l = r - k + 1; // 窗口左指针
if( q.isEmpty() ) q.add(r);//队列为空
else if( q.peekFirst() < l ){//队头滑出窗口
q.pollFirst();
}
//将r插入队列合适位置
while( !q.isEmpty() && nums[r] >= nums[ q.peekLast() ] ) q.pollLast();
q.add(r);
//一个合法窗口
if( l >= 0)
ans[index ++] = nums[ q.peekFirst( )];
}
return ans;
}
}