class MedianFinder {
Queue<Integer> A,B;
/** initialize your data structure here. */
public MedianFinder() {
A = new PriorityQueue<>();
B = new PriorityQueue<>((x,y)->(y-x));
}
public void addNum(int num) {
if(A.size()!=B.size()){
A.add(num);
B.add(A.poll());
}else{
B.add(num);
A.add(B.poll());
}
}
public double findMedian() {
if(A.size()!=B.size()){
return A.peek();
}else{
return (A.peek()+B.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();
*/
class MedianFinder {
Queue A,B;
public MedianFinder() {
A = new PriorityQueue<>();//小顶堆,存储数组较大的一部分
B = new PriorityQueue<>((x,y)->(y – x));//大顶堆,存储数组较小的一部分
}
共以下 10 个回答
时间复杂度:查找中位数O(1)
插入元素O(logn)
空间复杂度O(n)
解题思路
– 如果是通过数组维护底层(有序),添加元素后其他元素要后移,时间复杂度是O(n)
– 如果是通过2个堆(大顶堆和小顶堆)来维护底层,添加元素的时间复杂度是O(Logn)
– 具体如何维护这2个堆呢?
– 把数组分成2部分,左边是小的一部分,右边是大的一部分。右边最小的元素>=左边最大的元素
– 左边是大顶堆,右边是小顶堆。如果2边的数量相同,优先把多的那个放在右边。
– 放的过程很讲究,比如要把元素最终放在右边,不能直接放在右边,而是先放在左边之后取出左边的堆顶元素,把这个元素放在右边。想把元素最终放在左边也是类似的。(为什么要这样做?是为了维护性质“右边最小的元素>=左边最大的元素”)
【题解1】
大小顶堆
class MedianFinder {
}
思路:插入排序
时间:O(n)
空间:O(n)
思路: 构造 大顶堆 + 小顶堆 Java 使用 PriorityQueue 可实现 小顶堆
分别用大顶堆保存较小的数据,小顶堆保存较大的数据,堆顶的元素即为中位数。
时间复杂度:查找中位数O(1),添加元素O(longN),空间复杂度O(N)。
class MedianFinder { A,B;
Queue
public MedianFinder() {
A = new PriorityQueue<>();//小顶堆,存储数组较大的一部分
B = new PriorityQueue<>((x,y)->(y – x));//大顶堆,存储数组较小的一部分
}