题目链接
题目描述
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[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 范围内,你将如何优化你的算法?
解题思路
方法一:大顶堆和小顶堆
用一个大顶堆存小于等于中位数的一半值
用一个小顶堆存大于等于中位数的一半值
class MedianFinder {
PriorityQueue<Integer> minHeap, maxHeap;
public MedianFinder() {
// 小顶堆 堆顶是最小值 小顶堆里放的都是大于中位数的值
minHeap = new PriorityQueue<Integer>();
// 大顶堆 堆顶是最大值 大顶堆里放的都是小于等于中位数的值
maxHeap = new PriorityQueue<Integer>((a, b) -> b - a);
}
public void addNum(int num) {
minHeap.offer(num);
// 大顶堆中的值的个数大于等于小顶堆
if(maxHeap.size() < minHeap.size()){
maxHeap.offer(minHeap.poll());
}
// 如果小顶堆的最小值小于大顶堆的最大值,将两个值换位置
if(!minHeap.isEmpty() && maxHeap.peek() > minHeap.peek()){
minHeap.offer(maxHeap.poll());
maxHeap.offer(minHeap.poll());
}
}
public double findMedian() {
if(maxHeap.size() == minHeap.size()){
return (double)(maxHeap.peek() + minHeap.peek())/2.0;
}
return (double)maxHeap.peek();
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
class MedianFinder {
PriorityQueue<Integer> minHeap, maxHeap;
public MedianFinder() {
minHeap = new PriorityQueue<Integer>();
maxHeap = new PriorityQueue<Integer>((a, b) -> b - a);
}
public void addNum(int num) {
// 下面代码保证 minHeap 中的最小值大于 maxHeap 中的最大值
minHeap.offer(num);
// minHeap中最小的给maxHeap
maxHeap.offer(minHeap.poll());
// maxHeap中最大的给minHeap
if(minHeap.size() < maxHeap.size()){
minHeap.offer(maxHeap.poll());
}
}
public double findMedian() {
if(minHeap.size() > maxHeap.size()){
return (double)minHeap.peek();
}
return ((double)minHeap.peek() + (double)maxHeap.peek()) / 2.0;
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
- 时间复杂度 findMedian() O(1) addNum() O(log n)
- 空间复杂度 O(n)