题目:
方法一:
利用大顶堆,每次把k个数放进堆里,往右移,就把第一个数移出,后面的数加入,数组里面加入堆顶元素。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer i1,Integer i2){
return i2-i1;
}
});
//初始化堆
if(nums.length==0){
int[] arr = new int[0];
return arr;
}
if(maxHeap.size()==0){
for(int i=0;i<k;i++){
maxHeap.add(nums[i]);
}
}
int[] array = new int[nums.length-k+1];
for(int i=0;i<nums.length-k;i++){
array[i] = maxHeap.peek();
maxHeap.remove(nums[i]);
maxHeap.add(nums[i+k]);
}
if(maxHeap.size()!=0){
array[nums.length-k] = maxHeap.peek();
}
return array;
}
}
方法二:
利用双向队列,双向队列存储最大元素的下标,每一次在滑动窗体中,如果新加元素比前面的元素大,就把前面元素清除,最终保证最左边元素是最大的
class Solution {
ArrayDeque<Integer> deq = new ArrayDeque<Integer>();
int[] nums;
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length*k == 0) return new int[0];
if(k==1) return nums;
this.nums = nums;
int max_index=0;
for(int i =0;i<k;i++){
clean(i,k);
deq.addLast(i);
if(nums[i]>nums[max_index]){
max_index = i;
}
}
int[] output = new int[nums.length-k+1];
output[0] = nums[max_index];
for(int i=k;i<nums.length;i++){
clean(i,k);
deq.addLast(i);
output[i-k+1] = nums[deq.getFirst()];
}
return output;
}
public void clean(int i,int k){
if (!deq.isEmpty() && deq.getFirst() == i - k)
deq.removeFirst();
while(!deq.isEmpty() && nums[i] > nums[deq.getLast()]){
deq.removeLast();
}
}
}
-
时间复杂度:O(N),每个元素被处理两次- 其索引被添加到双向队列中和被双向队列删除。
-
空间复杂度:O(N),输出数组使用了 O(N−k+1) 空间,双向队列使用了O(k)。