「アルゴリズムの設計と解析」 - エッセイを選択するための線形時間

定義:濃度のn要素および整数k、1≤k≤n所与の線形順序は、小さい要素kのn個の要素のどれを識別するために頼みました。

(1)いくつかの特別なケースでは、問題を解決するための線形時間アルゴリズムを設計することは容易です。例えば:最大または最小要素要素は、明らかにO(N)時間で行うことができる場合に選択されます。(トリップさの比較)

(2)特に好みの中央値での一般的な選択は、最小値よりも硬くなるように(大)要素のようです。しかし、実際には、漸近的順序の意味で、彼らは同じです。また、O(n)の時間で達成することができます。

線形時間の選択方法:randomizedSelect

思考:適応は、(速い)クイックソートではなく、すべての種類の配列全体をランダム化しますが、ソート選択

時間計算:

(1)最悪の場合、アルゴリズムはrandomizedSelectはO(n ^ 2)の時間計算を必要とします

    (近いn)の最小の要素を探している場合例えば、得られたが、各時間分割位置パーティション関数が常に大きい(すなわち、常に最大の要素を分割)

(2)が、実証することができる、アルゴリズムは小さな平均時間はO(n)のk番目の要素でrandomizedSelect n個の入力要素を見つけることができます。

コードは以下の通りであります:

書式#include <iostreamの>
の#include <cstdioを>
する#include <アルゴリズム>
std名前空間を使用しました。
 
INTパーティション([]、int型P、INT rをINT){
    int型I = P、J = R + 1、X = A [P]。
    一方、(1){
        一方([++ i]の<X && I <R)
        一方、( - [J]> X)。
        もし(I> = j)をブレーク。
        スワップ([I]、[J])。
    }
    [P]は[j]を=。
    [J] = xと;
    Jを返します。
}
 
INT RandomizedPartition(INT A []、INT P、INT R){
    int型I =ランド()%(RP)+ P。
    スワップ([P]、[I])。
    リターンパーティション(P、R)。
}
 
INT RandomizedSelect(INT []、INT P、INT R、INT K){
    (Pの== r)この場合には、[P]を返します。
    int型I = RandomizedPartition(P 、R); // 要素の基準位置に戻す
    int型J = I-P + 1 ; //基準要素および左の要素の総数を表し
    ている場合(K <= J)RandomizedSelectを (A 、P、I、K);
    他RandomizedSelect(,. 1 + I、R&LT、キロジュール);
}
int型のmain(){
    int型A [10] = {3,1,7,6,5,9,8,2 、0,4};
    int型X;
    一方(scanfの( "%のD"、およびX)EOFを=!){
        int型RandomizedSelect ANS =(A、0,9、X)
        のprintf( "%d個の\ N-"、ANS) ;
    }
}
2を選択するための線形時間法:

一つは線形時間基準を分割することができる場合は、分割された基準に応じて2つのサブアレイの長さは、アレイ(0 <ε<1は正の定数である)の少なくともεの倍の長さであるように、それはあってもよいです最悪の場合にはO(n)の時間で選択したタスクを完了します。

例えば、= 9/10ε場合、アルゴリズムによって生成されたサブアレイ再帰呼び出しの長さは、少なくとも1/10を短縮します。したがって、最悪の場合には、アルゴリズムT(N)によって必要とされる計算時間は、漸化式T(N)(N)≤T(9N / 10)+ Oを満たします。それによりT(N)= O(N)を得ました。

すると先生は、私が「見つける」とは、行として、我々は中央値を見つける必要がありする値であり、我々が決定されている高速の前に位置値を見つけることが代わりに決定強調し、非常に明確覚えて、それは、参照要素であります正しい位置インチ

ステップ:

(1)要素は、それぞれ5つの要素から成る、N / 5(切り上げ)基、n個の入力に分割され、最大で5族元素ではないがあってもよいです。ソートアルゴリズムのいずれかを用いて、各グループ内の要素は、ソートされ、各グループの中央値、Nの合計/ 5(切り上げ)を除去しました。

(2)は、N / 5の中央値(切り上げ)の要素を見つけるために、再帰呼び出しを選択します。(切り上げ)N / 5た場合は、その2つの大きい方の中央値を見つけるために、偶数です。分割標準としてこの要素を持ちます。

パーティショニング戦略図:

白丸:各グループの中央値、点x:メジアンメディアン

例:

昇順に、以下の29個の要素の最初の18個の要素を見つける:8,31,60,33,17,4,51,57,49,35,11,43,37,3,13,52,6、 19,25,32、
    54,16,5,41,7,23,22,46,29。
エレメント25の前に(1)5(=フロア(5分の29))グループに分割される:(8、31 、60,33,17)、(4,51,57,49,35)、(11,43,37,3,13)、(52,6,19,25,32)、(54,16,5 、41,7)
;(2)各グループ内の要素の値を抽出し、コンフィギュレーションセット{31,49,13,25,16}
再帰的にMを得セットの中央値を求める(3)アルゴリズムを使用して= 25;
(4)M = 25によれば、素子29は、(元の順序に応じて)は、3つのサブアレイに分割されて
、P = {8,17,4,11、3,13,6,19,16,5,7 } 23,22
Q = {25}

R = {} 31,60,33,51,57,49,35,43,37,52,32,54,41,46,29

(5)ので、| P | = 13、| Q | = 1、K = 18、 これ= 18-13-1 = 4、kは、本アルゴリズムは、Rのために再帰的に実行されるように、P、Qを得;
(6)R 3(床(15/5))に分割されたグループ:31,60,33,51,57 {}、{} 49,35,43,37,52、32,54,41,46,29} {
(7 )要素の値の要素の三つのグループで得られるがある:{51,43,41}、設定値の要素が43である;
に分割されている(8)3基はR 43によると: 

{31、33、35,37,32、41、29}、{43}、{60、51,57、49、52,54、46}

複雑さ:

長さの配列を集合N
<75をn個の場合、使用される計算時間選択アルゴリズムは、いくつかの定数C1を超えない
forループ5の固定数、すなわち(定数とN / 5回、毎回実行されるとき、場合n≥75それはTに書き込むことができ、元の長さの1/5の長さから、中央値の中央値を見つける選択;!)を見つける(N / 10)が使用され、最も3N / 4要素にアレイを分割した後に得られました時間とT(3N / 4)と呼ばれます。したがって、T(n)は、のように再帰的に表すことができます。

この漸化式T(N)= O(N)の溶液

上記アルゴリズムの各グループのサイズは、カットオフポイントかのように、再帰呼び出しのための(より大きい75のアルゴリズムを使用して)5、75に設定され、選択されています。これは、二つの引数の再帰式2:00 T(n)を保証し、そしてN / 5 + 3N / 4 = 19N / 20 =εN、0 <ε<1。これは、T(N)=でキーO(N)です。もちろん、5および75に加えて、他のオプションがあります。

注意:

中央値(1)は、xとxよりも小さいが、少なくとも要素3 *(N-5)/ 10番目の理由よりも大きい場合、中央値Xに配置されています。

3 *(N / 5-1)* / 2

中央値は、xより小さい3つの要素が有するよりも、各グループ3 --- X小さいです

N / 5-1 ---グループ数の5ナンバー

1/2 ---約メジアン群の1/2 Xよりも小さいです

(2)場合n≥75、3(N-5)/ / 410≥nので、2つの部分をクリックし、得られた参照配列の長さに分割されていること少なくとも1/4より短く、それは元の長さまで、あります3/4の長さ。

示されるように、分割された左上部分は(おそらく1/4を占めている)のx比、右不確か左下及び上下右は確かに大きい(約1/4)、Xより確実小さくても二つの部分を同時に又はXよりも小さい場合Xよりも大きい、サブセクションに分割され、少なくとも1/4に短縮することができます!

コアコード:

選択タイプ([]、int型のP、R&LT INT、INT K型)
{
      IF(RP <75){
        //配列[P:R]単純ソートアルゴリズムでソートする;
        [+返す- K-Pを。1];
        };
      のために(INT I = 0;私は<=(4-RP)/ 5; Iは++)//私はパケットn個の要素の数であり、
      [P + 5には、// * I]に[P + 5 * I + 4 ] 及び第三小要素[P + I]交換部位;
      //正面に中央値のトランスデューサ素子は、
  
      //は、中央値の中央値を見つけ、RP-4、すなわち上記前記5-N-。
      タイプX =選択(P、P +(4-RP)/ 5、(4-RP)/ 10。。。); // Xは、中央値の中央値であり
      、I =パーティション(A int型、P、R、X)、 J = I-P + 1; // iは速い旅行を見つけるxの位置にあるべきである区間[P、R]を放電は、jは要素の数[P、i]の区間であります
      (K <= J)を選択(P、I、K)戻った場合
      、他の選択(,. 1 + I、R&LT、キロジュール)を返す
}
:キーコードであります

 

以下のために(; iはi = 0 int型 ; =(RP-4)/ 10 <Iは++) //パケットの数がIでのn個の要素である
      // [P + 5 * i]が[Pに+ 5 * I + 4]及び第三小要素[P + I]交換部位;
      //トランスデューサ素子の中央値の正面に
(R-P + 1)の合計/ 5

(RP-4)の合計、すなわち、0-(RP-4)/ 5、iは配列の添字への交換を容易にするために、0から示していることに注意してください/ 5 + 1各群において、すなわち、(RP + 1 )/ 5グループ

コードは以下の通りであります:

#include <iostreamの>
する#include <cstdioを>
する#include <CStringの>
する#include <スタック>
の#include <アルゴリズム>
名前空間STDを使用して、
 
ボイドバブルソート(INT []、INT P、INT R){
    {(; I <R iが++ iはpは= INT)のための
        ための(int型J = I + 1、J <= R; J ++){
            [(IF J] <[i])とスワップ([I]、[J])。
        }
    }
}
 
int型のパーティション(INT []、INT P、INT R、INTヴァル){
    POS int型。
    用(INT Q = P; Q <= R; Q ++){
        IF([Q] ==ヴァル){POS = Q;ブレーク;}
    }
    スワップ([P]、[POS])。
 
    INT I = P、J = R + 1、X = [P]。
    一方、(1){
        一方([++ i]の<X && I <R)
        一方、( - [J]> X)。

        スワップ([I]、A [J]);
    }
    A [P]は[J] =;
    [J] = X;
    Jを返す;
}
 
選択INT(INT A []、PをINT、INT R&LT、INT K){
    (RP <75){IF
        バブルソート(A、P、R&LT);
        戻り[P + K-1];
    }
 
    (I = 0をint型のために、私は=(RP-4 <)/ 5; I ++)は{//間隔切替[Pを、P + / 4(4-RP。)。]の各グループの中央値
        INTを5 * S = P + I、T = Sを+ 4;
        (INT J = 0; J < 3; J ++){//バブルソート、開始番号3増分良いためである(その結果、行)から
            (N-INT = Sため; N- <TJ; N - ++){
                IF([N-】 > [N- + 1])スワップ([N-]、[N - 1]);
            }
        }
        スワップ([P + I]、[S + 2]);各群の//交換フロント桁
    }
    //(4-RP)/ 5と、[P、Pの+(RP-、-1のグループ番号を表す 4)/ 5] 基の数は、間隔の長さに等しいです。
    INT X =選択(P 、Pの+(RP-4)/ 5、(RP-4)/ 10); // 中央値の中央値を見つける
    int型I =パーティション(P 、R、X) 、J = I-Pの+ 1;
    IF(K <= J)(A、P、I、K)の選択を返し、
    そうでなければ選択戻り(Aを、I + 1は、R、kJの);
}
int型のmain(){
    int型Xは、
    0から79までの配列を保存//
    INT [80] = {3,1,7,6,5,9,8,2,0,4、
               、13,11,17,16,15,19 18,12,10,14、
               23,21,27,26,25,29,28,22,20,24、
               33,31,37,36,35,39,38,32,30,34、
               43、 41,47,46,45,49,48,42,40,44、
               53,51,57,56,55,59,58,52,50,54、
               63,61,67,66,65,69、 68,62,60,64、
               73,71,77,76,75,79,78,72,70,74、
              };
    ながら(!scanfの( "%のD"、およびX)は、EOFを=){
        ;のprintf(X、選択(A、0,79、X) "多数の%dは%D \ N-である")
    }
}
HTTPS://blog.csdn.net/m0_37579232/article/details/説明80178000 
 

おすすめ

転載: blog.csdn.net/qq_40903237/article/details/94556287