题目链接
题目描述
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[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中最小的给maxHeapmaxHeap.offer(minHeap.poll());// maxHeap中最大的给minHeapif(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)
