F_G

许多问题需要说清楚就可以&&走永远比跑来的重要

导航

[Leetcode] Sliding Window Maximum

Sliding Window Maximum

Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.

For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.

Window position                Max
---------------               -----
[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

Therefore, return the max sliding window as [3,3,5,5,6,7].

刚开始想到是使用heap来保存当前遍历过的元素,并且保持最大堆状态,每当达到从堆中取出一个元素,则将当前节点之前的第k个元素从堆中删除,这样堆一直保持k的大小,整体算法的复杂度是O(N*k(logk)),从堆中删除需要找到需要找到节点,时间是O(K),删除O(Log(k)),最多N个节点。

 1     private int[] method2(int []nums,int k){
 2         if(nums.length==0) return nums;
       //递减排序方式
3 Comparator<Integer> compare = new Comparator<Integer>(){ 4 public int compare(Integer i1,Integer i2){ 5 return i2-i1; 6 } 7 }; 8 PriorityQueue<Integer> heap = new PriorityQueue<Integer>(compare); 9 int [] res = new int[nums.length-k+1]; 10 for(int i=0;i<nums.length;i++){ 11 heap.offer(nums[i]); 12 if(i>=(k-1)){ 13 res[i-k+1] = heap.peek(); 14 heap.remove(nums[i-k+1]); 15 } 16 } 17 return res; 18 } 19 public int[] maxSlidingWindow(int[] nums, int k) { 20 return method2(nums,k); 21 }

后来发现使用双端队列,就可以,并且时间复杂度降低到了O(N)

 1     private int[] method1(int[] nums, int k){
 2         if(nums.length==0) return nums;
 3         LinkedList<Integer> dequeue = new LinkedList<Integer>();
 4         int [] res = new int[nums.length-k+1];
 5         for(int i=0;i<nums.length;i++){
 6             int data = nums[i];
 7             //当data等于双端队列当中的最大值的时候,不能讲队列中的元素弹出,
 8             //原因是这个元素可能会被后面的某个元素视为最大元素,当前遇到的这个值虽然和双端队列当中目前的最大值是相等的,但是他出现的比较晚,在后面的窗口当中他可能会被用到。
 9             //举个例子 4444333,如果遇到想的就删除,那么
10             //4 4 4 4 变为空,遇到3的时候虽然窗口大小为3的窗口中的最大值是4,但是4已经不存在了,关键是在前面已经把他删除了。
11             
12             while(dequeue.size()!=0&&data>dequeue.getFirst()) dequeue.removeFirst();
13             dequeue.addFirst(data);
14             if(i>=k-1){
15                 int largest = dequeue.getLast();
16                 res[i-k+1] = largest;
17                 if(largest==nums[i-k+1]){
18                     dequeue.removeLast();
19                 }
20             }
21         }
22         return res;
23     }

这里的关键问题是while循环当中为甚me在当前data比队列中的第一个元素相等的时候,会保留相等元素,详细原因看参考代码中的注释。

 

posted on 2015-09-01 20:25  F_G  阅读(176)  评论(0编辑  收藏  举报