找滑动窗口的中位数

原文地址

找滑动窗口的中位数,主要思想利用堆,一个左边大顶堆,右边小顶堆,中间中位数。滑动窗口的过程中,添加新元素,删除不在窗口范围的老元素,并且调节两个堆的size保持平衡。

public class Solution {  
    public class minComparator implements Comparator<Integer> {  
        public int compare(Integer a, Integer b){  
            if(a > b) return 1;  
            else if(a == b) return 0;  
            else return -1;  
        }  
    }  
    public class maxComparator implements Comparator<Integer> {  
         public int compare(Integer a, Integer b){  
            if(a > b) return -1;  
            else if(a == b) return 0;  
            else return 1;  
        }  
    }  
    /** 
     * @param nums: A list of integers. 
     * @return: The median of the element inside the window at each moving. 
     */  
    public ArrayList<Integer> medianSlidingWindow(int[] nums, int k) {  
        // write your code here  
        ArrayList<Integer> res = new ArrayList<Integer>();  
        if(nums.length < k || k <= 0) {  
            return res;  
        }  
          
        PriorityQueue<Integer> minHeap = new PriorityQueue<Integer> (k, new minComparator());  
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer> (k, new maxComparator());  
          
        int median = nums[0];  
        for(int i = 1; i < k; i++){  
            if(nums[i] < median) {  
                maxHeap.offer(nums[i]);  
            }  
            else {  
                minHeap.offer(nums[i]);  
            }  
            if(maxHeap.size() > minHeap.size()){  
                minHeap.offer(median);  
                median = maxHeap.poll();  
            }  
            if(maxHeap.size() < minHeap.size()-1){  
                maxHeap.offer(median);  
                median = minHeap.poll();  
            }  
        }  
        res.add(median);  
          
        for(int i = k ; i < nums.length; i++){  
            // add new one  
            if(nums[i] < median) {  
                maxHeap.offer(nums[i]);  
            }  
            else {  
                minHeap.offer(nums[i]);  
            }  
  
            // remove the old out of heaps  
            int old = nums[i-k];  
            if(old == median) {  
                if(minHeap.size() > maxHeap.size()){  
                    median = minHeap.poll();  
                }  
                else {  
                    median = maxHeap.poll();  
                }  
            }  
            else if(old < median) {  
                maxHeap.remove(old);  
            }  
            else {  
                minHeap.remove(old);  
            }  
              
            while(maxHeap.size() > minHeap.size()){  
                minHeap.offer(median);  
                median = maxHeap.poll();  
            }  
            while(maxHeap.size() < (minHeap.size()-1)){  
                maxHeap.offer(median);  
                median = minHeap.poll();  
            }  
              
            res.add(median);  
        }  
          
        return res;  
    }  
}  
  
  
  
/////////////  
对于数组 [1,2,7,8,5], 滑动大小 k = 3 的窗口时,返回 [2,7,7]  
  
最初,窗口的数组是这样的:  
  
[ | 1,2,7 | ,8,5] , 返回中位数 2;  
  
接着,窗口继续向前滑动一次。  
  
[1, | 2,7,8 | ,5], 返回中位数 7;  
  
接着,窗口继续向前滑动一次。  
  
[1,2, | 7,8,5 | ], 返回中位数 7;  

 

posted @ 2017-09-04 15:57  南橘  阅读(330)  评论(0编辑  收藏  举报
蜘蛛