295.データストリームから中央値を検索

タイトルの説明

中央値は、順序付けされた整数リストの中央値です。リストのサイズが偶数の場合、中間値はありません。つまり、中央値は2つの中央値の平均です。

たとえば、[2,3,4]の場合、中央値は 3

[2,3]、中央値は (2 + 3) / 2 = 2.5

次の2つの操作をサポートするデータ構造を設計します。

  • void addNum(int num)-データストリームからデータ構造に整数を追加します。

  • double findMedian()-これまでのすべての要素の中央値を返します。

addNum(1)
addNum(2)
findMedian()-> 1.5
addNum(3)
findMedian()-> 2

ファローアップ

1.ストリームからのすべての整数が0〜100の場合、どのように最適化しますか?

2.ストリームからのすべての整数の99%が0〜100の場合、どのように最適化しますか?

難易度要因

ハード

解決策1:配列を作成し、バイナリ検索を使用する

class MedianFinder {
 public 
    MedianFinder(){ 
    
    } 
    // データ構造に数値を追加します
    void addNum(int num){
         int left = 0、right = nums.size()-1 ;
          // ループの条件は等しい場合、=条件の場合、
        while(左<= 右)
        { 
            int mid =(左+右)/ 2 ; if(nums [mid] <num)left = mid + を挿入するかどうかを判断する必要があります
             1 ;
             それ以外は right = 1 ; 
        }
        nums.insert(nums.begin()+ 左、num); 
    } 
 
    // 現在のデータストリームの中央値を返します
    double findMedian(){
         int n = nums.size();
        if(n%2 == 1return nums [n / 2 ];
        リターン(NUMS [N / 2 - 1 ] + NUMS [N / 2 ])/ 2.0 
    } 
プライベート
    ベクトル < int型 > NUMS。
};

 

 

解決策2:大きな上部ヒープと小さな上部ヒープをそれぞれ使用して、アレイを2つの半分に分割します。

class MedianFinder {
 private / * 
     *大きなトップヒープと小さなトップヒープを作成します。大きなトップヒープはデータの左半分を保存し、小さなトップヒープは右側の部分を保存します* / 
    // 小さなトップヒープ 
    priority_queue < int、vector < int >、great < int >> small;
     // デフォルトの大きなトップヒープ 
    priority_queue < int > large;
     void balance_heaps(){
         if(small.size()> large.size()+ 1 ){
             int moved = small.top(); 
            small.pop(); 
            large.push(移動); 
        } その他の 場合(large.size()> small.size()+ 1 ){
             int移動= large.top(); 
            large.pop(); 
            small.push(移動); 
        } 
    } 
public / * *ここでデータ構造を初期化します。* / 
    MedianFinder(){ 
        small.push(numeric_limits < int > :: max()); // コーナーケースのダミー値 
        large.push(numeric_limits < int > :: min()); 
    } 
    ボイド addNum(int型NUM){
         場合(NUM>small.top()){ 
            small.push(num); 
        } else { 
            large.push(num); 
        } 
        balance_heaps(); 
    } 
    ダブルfindMedian(){
         場合(small.size()== 1 && large.size()== 1 戻り 0 ; // なし番号
        場合(small.size()== large.size()){ // 偶数的情况
            リターン(small.top()+ large.top())/ 2.0 
        } else  if(small.size()> large.size()){ //奇数的状況
            return small.top(); 
        } else {
             return large.top(); 
        } 
    } 
}。
 
/ * * 
 * MedianFinderオブジェクトはインスタンス化され、次のように呼び出されます。
 * MedianFinder * obj = new MedianFinder(); 
 * obj-> addNum(num); 
 * double param_2 = obj-> findMedian(); 
 * /

 

 

おすすめ

転載: www.cnblogs.com/AntonioSu/p/12735120.html