中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2
进阶:
如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?
学习,代码来自leetcodecn评论
//大堆的元素个数要始终小于等于小堆的元素个数 超值不超过1,大堆的最大值要始终<= 小堆的最小值
class MedianFinder {
//容量
private int size;
//维护较小元素的最大堆
private PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b)->b-a);
//维护较大的元素的最小堆
private PriorityQueue<Integer> minPQ = new PriorityQueue<>();
/** initialize your data structure here. */
public MedianFinder() {
}
public void addNum(int num) {
//插右边
if (maxPQ.size() > minPQ.size()) {
minPQ.offer(num);
} else {
maxPQ.offer(num);
}
size++;
if (size == 1) return;
while (maxPQ.peek() > minPQ.peek()) {
//交换两个极值
int val1 = maxPQ.poll();
int val2 = minPQ.poll();
minPQ.offer(val1);
maxPQ.offer(val2);
}
}
public double findMedian() {
if (size == 0) return 0;
if (maxPQ.size() > minPQ.size()) return maxPQ.peek();
return (maxPQ.peek() + minPQ.peek()) / 2.0;
}
}
public class PriorityQueue
一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。优先级队列不允许使用 null 元素。依靠自然顺序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)。
此队列的头 是按指定排序方式确定的最小 元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。队列获取操作 poll、remove、peek 和 element 访问处于队列头的元素。