题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
思路
- 构建最大堆,最小堆。最小堆是从小到大排序,最大堆是从大到小排序。最小堆中每个数都大于等于最大堆里的每个数。
- 插入时,第偶数个放在最大堆。然后将最大堆的第一个数(最大堆的最大值)弹出放入最小堆
- 同理第奇数个放入最小堆,然后将最小堆的第一个数(最小堆最小值)弹出放入最大堆中
- 获取中位数时,判断插入了多少个数。如果是奇数个,则返回最小堆的堆顶元素即可。如果插入了偶数个,则返回最大堆和最小堆的堆顶元素的平均值。
代码实现
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
// 最小堆,里面按照从小到达的顺序。里面每个数都大于等于最大堆
private PriorityQueue<Integer> min = new PriorityQueue<>();
// 最大堆,里面按照从大到小的顺序
private PriorityQueue<Integer> max = new PriorityQueue<>(15, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
int count = 0;
public void Insert(Integer num) {
// 偶数时,数放入最大堆,在最大堆里面的最大值放入最小堆
if (count % 2 == 0) {
max.add(num);
int big = max.poll();
min.add(big);
} else {
min.add(num);
int small = min.poll();
max.add(small);
}
count++;
}
public Double GetMedian() {
if (count % 2 == 0) {
return new Double(min.peek() + max.peek()) / 2.0;
} else {
return new Double(min.peek());
}
}
}