題目:
方法一:
利用大頂堆,每次把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)。