题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数
直接排序:
class Solution { vector<int> numbers; public: void Insert(int num) { numbers.push_back(num); sort(numbers.begin(),numbers.end()); } double GetMedian() { int len = numbers.size(); if(len %2 == 0) return (numbers[len/2-1]+numbers[len/2])/2.0; else return numbers[len/2]; } };
使用一个大顶堆和一个小顶堆来完成:
class Solution { priority_queue<int,vector<int>,greater<int> > smallCap; priority_queue<int,vector<int>,less<int> > bigCap; public: void Insert(int num) { if(smallCap.size() == 0 && bigCap.size() == 0) smallCap.push(num); else if(smallCap.size()==bigCap.size()){ if(num<smallCap.top()) bigCap.push(num); else smallCap.push(num); }else if(smallCap.size()-bigCap.size() == 1){ if(num<smallCap.top()) bigCap.push(num); else{ bigCap.push(smallCap.top()); smallCap.pop(); smallCap.push(num); } }else if(smallCap.size()-bigCap.size() == -1){ if(num<smallCap.top()&&num<bigCap.top()){ smallCap.push(bigCap.top()); bigCap.pop(); bigCap.push(num); } else{ smallCap.push(num); } }else{ return; } } double GetMedian() { if(smallCap.size() == bigCap.size()){ return (smallCap.top() + bigCap.top())/2.0; }else if(smallCap.size()-bigCap.size() == 1){ return smallCap.top(); }else{ return bigCap.top(); } } };
使用堆的方式可以达到插入为O(logn),取中位数为O(1)的时间复杂度
java实现的更加简洁的写法:
import java.util.*; public class Solution { public Comparator<Integer> cmp = new Comparator<Integer>() { public int compare(Integer e1,Integer e2){ return e2 - e1; } }; private PriorityQueue<Integer> minHeap = new PriorityQueue<>(); private PriorityQueue<Integer> maxHeap = new PriorityQueue<>(cmp); int count = 0; public void Insert(Integer num) { if((count & 1) == 0){//偶数个,先插入大顶堆,再弹出大顶堆最大元素放入小顶堆 maxHeap.offer(num); minHeap.offer(maxHeap.poll()); }else{//奇数个,先插入小顶堆,再弹出小顶堆最小元素放入大顶堆 minHeap.offer(num); maxHeap.offer(minHeap.poll()); } count++; } public Double GetMedian() { if((count & 1) == 1) return minHeap.peek().doubleValue(); else return (minHeap.peek()+maxHeap.peek())/2.0; } }