I have to find the running median as per this problem: https://www.hackerrank.com/challenges/ctci-find-the-running-median
I am trying to implement two heaps. A min heap which stores the elements lesser than the current median and a max heap which stores items greater than the current median.
The median keeps changing, and the difference in number of elements in both heaps does not exceed 1.
My code however is not being accepted. However it has passed test cases I could think of.
Please only read the main function and the update median function! Any help is appreciated.
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
class max_heap{
private:
vector<int> items;
int size;
public:
max_heap(){
size=0;
}
int left(int parent){ return (parent*2 + 1); }
int right(int parent){ return (parent*2 + 2); }
int parent(int pos){ return pos<=0 ? 0 : (pos-1)/2; }
int getmax(){ return items[0]; }
int peek(int pos){ return items[pos];}
int length(){ return items.size();}
void swap(int pos1, int pos2){
int tmp=items[pos1];
items[pos1]=items[pos2];
items[pos2]=tmp;
return;
}
void insert(int key)
{
if(items.size()==size)
items.pb(key);
else
items[size]=key;
//fixing items property
int tmp=size;
while(items[0]!=key && items[parent(tmp)] < key ){
swap( parent(tmp), tmp);
tmp=parent(tmp);
}
size++;
}
int pop(){
if(size==0)
return 0;
int ans=getmax();
size--;
items[0]=items[size];
//fix items
int i=0;
while(i<size-1){
bool a = items[i] < items[right(i)];
bool b = items[i] < items[left(i)];
if( a && b)
{
if( items[left(i)] < items[right(i)] )
swap(i,left(i));
else swap(i,right(i));
}
else if(a)
swap(i,right(i));
else if(b)
swap(i,left(i));
else break;
}
return ans;
}
void print(){
for (int i = 0; i < items.size(); ++i)
cout<<items[i]<<" ";
cout<<endl;
}
};
class min_heap{
private:
vector<int> items;
int size;
public:
min_heap(){
size=0;
}
int left(int parent){ return (parent*2 + 1); }
int right(int parent){ return (parent*2 + 2); }
int parent(int pos){ return pos<=0 ? 0 : (pos-1)/2; }
int getmin(){ return items[0]; }
int peek(int pos){ return items[pos];}
int length(){ return items.size();}
void swap(int pos1, int pos2){
int tmp=items[pos1];
items[pos1]=items[pos2];
items[pos2]=tmp;
return;
}
void insert(int key)
{
if(items.size()==size)
items.pb(key);
else
items[size]=key;
//fixing items property
int tmp=size;
while(items[0]!=key && items[parent(tmp)] > key ){
swap( parent(tmp), tmp);
tmp=parent(tmp);
}
size++;
}
int pop(){
if(size==0)
return 0;
int ans=getmin();
size--;
items[0]=items[size];
//fix items
int i=0;
while(i<size-1){
bool a = items[i] > items[right(i)];
bool b = items[i] > items[left(i)];
if( a && b)
{
if( items[left(i)] < items[right(i)] )
swap(i,left(i));
else swap(i,right(i));
}
else if(a)
swap(i,right(i));
else if(b)
swap(i,left(i));
else break;
}
return ans;
}
void print(){
for (int i = 0; i < items.size(); ++i)
cout<<items[i]<<" ";
cout<<endl;
}
};
double update_median(int element, int median, min_heap &mn_heap, max_heap &mx_heap)
{
int path = mx_heap.length() - mn_heap.length();
double ans=0.0;
switch(path){
case 0:
if( element > median ){
//push to right heap..ie the min heap
mn_heap.insert(element);
ans= mn_heap.getmin();
}
else
{
//push to left heap....ie max heap
mx_heap.insert(element);
ans= mx_heap.getmax();
}
break;
case 1: //max heap is greater ie left
if( element > median )
{ //push to right heap...min heap
mn_heap.insert(element);
ans=(mn_heap.getmin() + mx_heap.getmax()) / 2.0;
}
else
{
mn_heap.insert(mx_heap.pop());
mx_heap.insert(element);
ans= (mn_heap.getmin() + mx_heap.getmax()) / 2.0;
}
break;
case -1: // min heap greater ie right
if( element > median )
{ //push to right heap...min heap
mx_heap.insert(mn_heap.pop());
mn_heap.insert(element);
ans=(mn_heap.getmin() + mx_heap.getmax()) / 2.0;
}
else
{
mx_heap.insert(element);
ans= (mn_heap.getmin() + mx_heap.getmax()) / 2.0;
}
break;
}
return ans;
}
int main(){
cout.sync_with_stdio(false);
int el;
cin>>el;
double median=0.0;
min_heap *a = new min_heap(); //items less than median
max_heap *b = new max_heap(); //items more than median
while(el--){
int element;
cin>>element;
median= update_median(element,median,*a,*b);
printf("%.1lf\n", median);
}
}
I think the problem is in the
pop
method of yourmax_heap
implementation. You have:That always swaps the parent with the smaller of the two children. In a max heap you want to swap the parent with the larger of the two children. Your
min_heap
implementation also swaps the parent with the smaller of the two children, which is correct.