原题
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。 你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。
- 来源:力扣(LeetCode)
- 难度:困难
- 链接:leetcode-cn.com/problems/sl…
解法
单列队列
单列队列解决:保证单列队列递减性质
- 通过保存索引来维持最大值在队首
- 遍历,初始化窗口
- 第一个窗口最大值,存入ans[0]
- 遍历,比前者大的就替换,前者(队尾)出队,后者(新元素)入队
- 判断窗体移动,判断队首索引是否在窗体内,不在就删除
- i+1-k下标存储第i+1个窗体最大值
public int[] maxSlidindWindow(int[] nums,int k){
Deque<Integer> deque = new LinkedList<>();
int n = nums.length;
for (int i =0;i<k;++i){//第一组窗口形成
while(!deque.isEmpty()&&nums[i]>nums[deque.peekLast()]){//比前者大的就替换,前者(队尾)出队,后者入队
deque.pollLast();//比如是11 12,那么11出队
}
deque.offerLast(i);
}
int[] ans = new int[n-k+1];//结果数组
ans[0] = nums[deque.peekFirst()];//第一个永远最大
for(int i=k;i<n;++i){
while(!deque.isEmpty()&&nums[i]>nums[deque.peekLast()]){//比前者大的就替换,前者(队尾)出队,后者入队
deque.pollLast();//比如是11 12,那么11出队
}
deque.offerLast(i);
//重点!下面判断窗体移动,判断队首索引是否在窗体内,不在就删除
//i+1-k代表新窗体实际范围之外的位置,deque.peekFirst()+1表示队首索引在实际位置
while (deque.peekFirst()<=i-k){//deque.peekFirst()+1 <= i+1-k
deque.pollFirst();
}
//i-k+1即第几个窗体
ans[i-k+1] = nums[deque.peekFirst()];
}
return ans;
}