2016-12-27 49 views
-6

我必須要找到運行中位數按這樣的問題: 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); 
    } 
} 
+2

歡迎來到Stack Overflow。請花些時間閱讀[The Tour](http://stackoverflow.com/tour),並參閱[幫助中心](http://stackoverflow.com/help/asking)中的資料,瞭解您可以在這裏問。 –

+2

解決這些問題的正確工具是您的調試器。在*堆棧溢出問題之前,您應該逐行執行您的代碼。如需更多幫助,請閱讀[如何調試小程序(由Eric Lippert撰寫)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。至少,您應該\編輯您的問題,以包含一個[最小,完整和可驗證](http://stackoverflow.com/help/mcve)示例,該示例再現了您的問題,以及您在調試器。 –

+0

如果兩個堆之間的差異永遠不會超過1,那麼您只需要保留每個堆的一個元素。 – stark

回答

0

我認爲這個問題是在你的max_heap實施pop方法。您有:

if(a && b) 
    { 
     if(items[left(i)] < items[right(i)]) 
      swap(i,left(i)); 
     else swap(i,right(i)); 

    } 

總是交換與兩個孩子的父。在一個最大的堆中,你想交換父母與兩個孩子的較大的。您的min_heap實施也將父母與兩個孩子中較小的孩子交換,這是正確的。

+0

我修正了錯誤,但我仍然得到錯誤的代碼提交答案:( –