【发布时间】:2017-05-12 02:15:39
【问题描述】:
我必须根据这个问题找到运行中位数: https://www.hackerrank.com/challenges/ctci-find-the-running-median
我正在尝试实现两个堆。存储小于当前中值的元素的最小堆和存储大于当前中值的元素的最大堆。
中位数不断变化,两个堆的元素个数相差不超过1。
但是我的代码没有被接受。但是它已经通过了我能想到的测试用例。
请只看主函数和更新中值函数! 任何帮助表示赞赏。
#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);
}
}
【问题讨论】:
-
欢迎来到 Stack Overflow。请花时间阅读The Tour 并参考Help Center 中的材料,您可以在这里问什么以及如何问。
-
调试器是解决此类问题的正确工具。 在询问 Stack Overflow 之前,您应该逐行逐行检查您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
-
如果两个堆之间的差异不超过 1,那么您只需要保留每个堆的一个元素。