中位数简介
-
找出这组数据:23、29、20、32、23、21、33、25 的中位数。
首先将该组数据进行排列(这里按从小到大的顺序),得到:
20、21、23、23、25、29、32、33
因为该组数据一共由8个数据组成,即n为偶数,故按中位数的计算方法,得到中位数,即第四个数和第五个数的平均数。
midval = (23+25)/2 = 24 -
找出这组数据:10、30、 20、 20、 20的中位数。
首先将该组数据进行排列10、 20、 20、 20、 30
因为该组数据一共由5个数据组成,即n为奇数,故按中位数的计算方法,得到中位数为20,即第3个数。
具体实现:
1.创建大顶堆(这里使用优先队列等效成大顶堆)queue2,和小顶堆queue1。(大顶堆弹出元素,先弹出大的值;小顶堆弹出元素,首先弹出值小的元素)
class MedianFinder {
private Queue<Integer> smallQ, bigQ;
public MedianFinder() {
smallQ = new PriorityQueue<>(); // 小顶堆,保存较大的一半
bigQ = new PriorityQueue<>((x, y) -> (y - x)); // 大顶堆,保存较小的一半
}
public void addNum(int num) {
// 奇数个数
if (((bigQ.size() + smallQ.size()) & 1) == 1) {
smallQ.add(num);
} else {
bigQ.add(num);
}
// 大顶堆的头(左侧较小的数中最大值) > 小顶堆的头(右侧较大的数中最小的值)
// 则需要调换顺序
if (bigQ.size() > 0 && smallQ.size() > 0 && bigQ.peek() > smallQ.peek()) {
Integer big = bigQ.poll();
Integer small = smallQ.poll();
smallQ.add(big);
bigQ.add(small);
}
}
public double findMedian() {
return ((bigQ.size() + smallQ.size()) & 1) == 1 ? bigQ.peek() : (bigQ.peek() + smallQ.peek()) / 2.0;
}
}
测试
public static void main(String[] args) {
MedianFinder finder = new MedianFinder();
List<Integer> list = Lists.newArrayList(10,30,40,20,50);
for (Integer item : list) {
finder.addNum(item);
double median = finder.findMedian();
System.out.println(median);
}
}