利用PriorityQueue求动态数据流中的中位数
数据流中的中位数
http://www.nowcoder.com/questionTerminal/9be0172896bd43948f8a32fb954e1be1
使用大小顶堆来进行插入时排序。
需要求的是中位数,如果我将 1 2 3 4 5 6 7 8定为最终的数据流
此时的中位数是4+5求均值。为什么是4,为什么是5
利用队列我们就可以看得很清楚,4是前半部分最大的值,肯定是维系在大顶堆
而5是后半部分的最小值,肯定是维系在小顶堆。
问题就好理解了:
使用小顶堆存大数据,使用大顶堆存小数据。这样堆顶一取出就是中位数了。
import java.util.*;
public class Solution {
private int cnt = 0;
//默认的小顶堆
private PriorityQueue<Integer> low = new PriorityQueue<>();
//重写为大顶堆
private PriorityQueue<Integer> high = new PriorityQueue<>(new Comparator<Integer>(){
public int compare(Integer o1, Integer o2){
return o2.compareTo(o1);
}
});
public void Insert(Integer num) {
//数量++
cnt++;
if((cnt & 1) == 1){ //数据流为奇数
if(!low.isEmpty() && num > low.peek()){
low.offer(num);
//会吐出最小的数
num = low.poll();
}
high.offer(num);
}else{
if(!high.isEmpty() && num < high.peek()){
high.offer(num);
//大顶堆最小的数,在小顶堆就是最大的数
num = high.poll();
}
low.offer(num);
}
}
public Double GetMedian() {
double res = 0;
if((cnt & 1) == 1){
res = high.peek();
}else{
res = (high.peek() +low.peek()) / 2.0;
}
return res;
}
}其实除此之外还有其他几个思路: * 使用无序数组存储,在得到中位数前对数组进行排序。(这是最容易想到的)
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
ArrayList<Integer> array = new ArrayList<>();
public void Insert(Integer num) {
array.add(num);
}
public Double GetMedian() {
Collections.sort(array);
int index = array.size()/2;
if(array.size()%2 != 0){ //奇数直接取
return (double)array.get(index);
}
return ((double)(array.get(index-1))+(double)array.get(index))/2;//偶数平均值
}
}- 插入时排序,不利用堆,而是利用二分法。
import java.util.LinkedList;
import java.util.List;
public class Solution {
private List<Integer> list = new LinkedList();
public void Insert(Integer num) {
if(list.size()==0){
list.add(num);
return;
}
int first = 0;
int last = list.size()-1;
int mid = 0;
while(first <= last){
mid = (first+last)/2;
if(list.get(mid)>num)
last = mid-1;
else
first = mid+1;
}
list.add(first,num);
return;
}
public Double GetMedian() {
int index = list.size();
if(index%2==1){
return (double)list.get(index/2);
}
return ((double)(list.get(index/2-1))+(double)list.get(index/2))/2;
}
}
阿里云成长空间 745人发布