面接問題:top kアルゴリズムO(n)時間複雑度
3529 ワード
「データ構造とアルゴリズム分析--c言語記述」という本、第7章7.7.6節では、平均的な場合、時間複雑度が S中の1つの要素をピボットvとして選択し、集合S-{v}をS 1とS 2に分割し、高速ソートのように k<=|S 1|の場合、k番目の最小要素は必ずS 1にある.この場合、QuickSelect(S 1,k)が返される. k=1+|S 1|の場合、ピボット要素はk番目の最小要素であり、すなわち見つけられ、直接それに戻る. それ以外の場合、k番目の最小要素はS 2、すなわちS 2の(k-|S 1|-1)番目の最小要素であり、QuickSelect(S 2、k-|S 1|-1)を再帰的に呼び出して返す.
このアルゴリズムの平均運転時間はO(n)である.
サンプルコードは次のとおりです.
この高速選択SELECTアルゴリズムは,高速ソートの分割方法に似ている.N個の数を配列Sに格納し、配列から「中位数の中位数」をピボットXとして選択し、配列をSaとSbの2つの部分に分割し、Sa<=X<=Sbとし、検索するk個の要素がSaの要素の数より小さい場合はSaの中の小さいk個の要素を返し、そうでない場合はSaの中にある要素+Sbの中の小さいk-|Sa|個の要素を返し、この解法は平均的に
さらに,「アルゴリズム導論」9章9.3節では,最悪の場合でもO(n)時間のSELECTアルゴリズムを紹介し,興味のある読者は参照できる.
O(N)
の高速選択アルゴリズムについて述べた.次のようになります.このアルゴリズムの平均運転時間はO(n)である.
サンプルコードは次のとおりです.
//QuickSelect k a[k-1]
void QuickSelect( int a[], int k, int left, int right )
{
int i, j;
int pivot;
if( left + cutoff <= right )
{
pivot = median3( a, left, right );
// ,
i = left; j = right - 1;
for( ; ; )
{
while( a[ ++i ] < pivot ){ }
while( a[ --j ] > pivot ){ }
if( i < j )
swap( &a[ i ], &a[ j ] );
else
break;
}
//
swap( &a[ i ], &a[ right - 1 ] );
if( k <= i )
QuickSelect( a, k, left, i - 1 );
else if( k > i + 1 )
QuickSelect( a, k, i + 1, right );
}
else
InsertSort( a + left, right - left + 1 );
}
この高速選択SELECTアルゴリズムは,高速ソートの分割方法に似ている.N個の数を配列Sに格納し、配列から「中位数の中位数」をピボットXとして選択し、配列をSaとSbの2つの部分に分割し、Sa<=X<=Sbとし、検索するk個の要素がSaの要素の数より小さい場合はSaの中の小さいk個の要素を返し、そうでない場合はSaの中にある要素+Sbの中の小さいk-|Sa|個の要素を返し、この解法は平均的に
O(n)
の複雑さを実現することができる.さらに,「アルゴリズム導論」9章9.3節では,最悪の場合でもO(n)時間のSELECTアルゴリズムを紹介し,興味のある読者は参照できる.