给你一个整数数组
nums
,有一个大小为k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的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
如果你刚看见这道题你会怎么想?三秒告诉我?3...2...1...,时间到!!!
首先是滑动窗口,一听到这个名字,我们就应该立刻的想到双指针,双指针这个大方向是错不了,我们再看,要每次取到范围内的最大值,除了最大堆就是优先队列可以做到这件事,接下来我们先用最大堆进行解题
最大堆就是其实就是一棵树,通过上浮和下浮使得堆顶是最大值或者最小值,Java中默认是最小堆,所以我们如果是想每次取到范围内的最大值,
PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;//最大值 默认是o1-o2
}
});
需要对堆的比较器进行重写,构造一个最大堆
维护一个一个列表进行最大值的维护
List<Integer> list=new ArrayList<>();
for(int right=0;right< nums.length;right++){
if(right<k-1){
queue.offer(nums[right]);
}else{
queue.offer(nums[right]);
list.add(queue.peek());
queue.remove(nums[left++]);
}
}
结果,不出意外:
怎么办?时间超时了怎么办?堆的上浮和下沉确实浪费了大量的时间,所以我们使用另外一种数据结构解决本题(优先队列)
//维护一个单调队列
class MaxQueue{
private LinkedList<Integer> queue=new LinkedList<>();
//添加
public void push(int x){
//队列不为空,队尾元素如果小于当家加入元素,直接扔出去
while(!queue.isEmpty()&&queue.getLast()<x){
queue.pollLast();
}
queue.addLast(x);
}
//删除
public void pop(int x){
if(x==queue.getFirst()){
queue.pollFirst();
}
}
//得到最大值
public Integer getMax(){
return queue.getFirst();
}
}
核心代码:
int left=0;
for(int right=0;right< nums.length;right++){
if(right<k-1){
window.push(nums[right]);
}else{
window.push(nums[right]);
list.add(window.getMax());
window.pop(nums[left++]);
}
}
结果,不出意外:
上源代码:
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums==null){
return null;
}
MaxQueue window=new MaxQueue();
List<Integer> list=new ArrayList<>();
int left=0;
for(int right=0;right< nums.length;right++){
if(right<k-1){
window.push(nums[right]);
}else{
window.push(nums[right]);
list.add(window.getMax());
window.pop(nums[left++]);
}
}
return list.stream().mapToInt(Integer::valueOf).toArray();
}
//维护一个单调队列
class MaxQueue{
private LinkedList<Integer> queue=new LinkedList<>();
//添加
public void push(int x){
while(!queue.isEmpty()&&queue.getLast()<x){
queue.pollLast();
}
queue.addLast(x);
}
//删除
public void pop(int x){
if(x==queue.getFirst()){
queue.pollFirst();
}
}
//得到最大值
public Integer getMax(){
return queue.getFirst();
}
}