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