原文地址
找滑动窗口的中位数,主要思想利用堆,一个左边大顶堆,右边小顶堆,中间中位数。滑动窗口的过程中,添加新元素,删除不在窗口范围的老元素,并且调节两个堆的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;