题目描述如下:
要求插入的时间复杂度是O(logN),取中位数的时间复杂度是O(1)
想到用优先队列priority_queue,插入时可以动态实现堆的调整
思路:
用大根堆存 <=中位数的那部分数,smallPart,存n/2个
用小根堆存 >= 中位数的那部分数,bigPart,存n/2或n/2+1个
priority_queue<double> smallPart;//大根堆存储小的那部分
priority_queue<double,vector<double>,greater<double>> bigPart;//小根堆存储大的那部分
即小根堆要么比大根堆多存一个(小根堆顶即中位数),要么存的一样多(两个堆顶和的平均数)
①当小根堆存的数 多于 大根堆时:应存到大根堆,又因为当前数可能比小根堆的堆顶大,所以先插到小根堆,再将小根堆堆顶pop出来,插到大根堆堆顶
if(bigPart.size()>smallPart.size()){
bigPart.push(num);
smallPart.push(bigPart.top());
bigPart.pop();
}
②当小根堆存的数 等于 大根堆时:应存到小根根堆,又因为当前数可能比大根堆的堆顶小,所以先插到大根堆,再将大根堆堆顶pop出来,插到小根堆堆顶
else{
smallPart.push(num);
bigPart.push(smallPart.top());
smallPart.pop();
}
③取的时候就很好判断了:如果小根堆存的比大根堆多,说明奇数个,小根堆堆顶即为中位数;否则偶数个,取两个的平均数
double findMedian() {
if(bigPart.size()==smallPart.size())
return (bigPart.top()+smallPart.top())/2;
else return bigPart.top();
}
----------------------------------------这是分界线---------------------------------------
上面优先队列的push()、pop()实现了堆的插入、删除后的堆调整,其实也可以自己实现,顺便复习一下堆的知识
①堆的插入:
只能插入到最后一个位置,size++,然后从最后一个非叶子节点开始、向堆顶遍历调整堆
//堆的增加操作,必须是增加在最后一个节点
void addHeap(vector<int> &input,int newNum){
int i;
int n=input.size();
input.push_back(newNum);
n++;