题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
分析:建立2个大根堆,一个max用于存放数据中较小的部分,一个min存放较大的部分。整体思路是最后若max+min的个数为奇数则middle=max.last(用于取出最大的数)。若为偶数,则middle=(max.last+min.first)/2.0(即max的最大数和min的最小数的平均值)。这就是GetMedian()函数。
而insert()函数,是用于存放数据的,该如何有序存放。开始max和min都为空,将一个数存入max.add(num)。再来一个数,则需要放一个数到min中去,直接放?当然不是。需要将num和max.last()比较。若num<max.last(),即第二个数比第一个数小,那么此时应该将num放入max中,然后取出max中最大的数放入Min中。第三个数也如此,总之这三个数有2个是要放在max中。至此就可以归纳出偶数个时,放max中,奇数个数放min中。
import java.util.TreeSet;
/*
* 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
* 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
* 我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
*/
public class GetMedian1 {
TreeSet<Integer> max =new TreeSet<Integer>();
TreeSet<Integer> min =new TreeSet<Integer>();
public void Insert(Integer num) {
if((max.size()+min.size())%2==0){
if(min.size()>0&&num>min.last()){
min.add(num);
num=min.first();
min.remove(num);
}
max.add(num);
}else{
if(max.size()>0&&num<max.first()){
max.add(num);
num=max.last();
max.remove(num);
}
min.add(num);
}
}
public Double GetMedian() {
int size =max.size()+min.size();
if(size==0){
return 0.0;
}
if(size%2==0){
return ((max.last()+min.first())/2.0);
}else{
return (double)max.last();
}
}
}
参考:https://blog.csdn.net/junjunba2689/article/details/80661948