回答:
Tを並べ替えます。次に、要素を取得しT[i] >= i+1
ます。
たとえばsorted(T)=[6,4,3,3,1,1]
。その後、T[0] = 6 > 1
、T[1] = 4 > 2
、T[2] = 3 <= 3
そして最後に、T[3] = 3 < 4
私たちは持っているのでS = [T[0], T[1], T[2]]
。
私の元々のコメントから:これは、学術生産性評価における遍在する量であるHirshインデックスと密接に関連しています。これは -indexとして知られています。要するに、それぞれが少なくともhの引用(そのようなhの最大のもの)を持つようなの出版物の数として定義されます。
あなたの問題が異なる唯一の方法は、基準を満たす出版物の数だけでなく、それらの引用カウントが何であるかに興味があるということですが、それは些細な修正です。データはすでにそこにあり、元のアルゴリズムはそれをドロップします。
一般的に実行される計算はかなり簡単で、カロリス・ジュオデルの答えに同意します。
更新:データのサイズと文字に応じて、ピボットポイントの上下のデータをフィルター処理して配列を部分的に並べ替える方法を検討する価値があります(クイックソートが思い浮かびます)。次に、ピボットが少なすぎるか多すぎるかによって、ピボットを調整し、それを含むサブセットで再実行します。より高い要素間の順序は必要ありません。また、それより低い要素間の順序は確かに必要ありません。したがって、たとえば、h 1以上のすべての要素が見つかり、それらの要素がh 1未満になったら、そのサブセットに再度触れる必要はなく、追加するだけです。これは、クイックソートに固有の再帰変換末尾再帰ので、ループのように書き換えることができるが。
私のHaskellは少しさびていますが、これは私が上で説明したことをするはずで、うまくいくようです。ある程度理解できることを願って、さらに説明をさせていただきます。
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
アイデアはgranted
、結果に間違いなく参加することがわかっているものを収集し、それ以上ソートしないことです。はめあいgreater
とx
合わせれば幸運です。さもなければ、より小さいサブセットで試す必要があります。(ピボットx
は、現在考慮されているサブリストの最初の項目であるものです。)最大の要素を1つずつ取得することに対する大きな利点は、平均サイズブロックでこれを行うことです。g / 2で、さらに並べ替える必要はありません。
例:
セットを取りましょう[1,3,4,1,3,6]
。
x = 1
、granted = []
、greater = [3,4,1,3,6]
。smaller
最初のステップでピボットが小さすぎる(実際には非常に小さいため空になっている)場合、病理学的なケースにぶつかります。幸いなことに、私たちのアルゴリズムはその準備ができています。破棄x
して、greater
単独で再試行します。
x = 3
、granted = []
、greater = [4,3,6]
。一緒に、それらは長さ4の配列を形成しますが、下から3だけに制限されているため、多すぎます。greater
単独で繰り返します。
x = 4
、granted = []
、greater = [6]
。これにより、それぞれ4以上の2つの要素の配列が得られ、さらにいくつかの要素に使用できる可能性があります。これを保持し、繰り返しsmaller = [3]
ます。
x = 3
、granted = [4,6]
、greater = []
。これにより、それぞれ3つ以上の3つの要素の配列が得られるため、解決策が得られ[3,4,6]
、戻ることができます。(順列は、入力の順序によって異なりますが、常に決して、可能な限り最高の条件が含まれていないことに注意してください[3,3,6]
または[3,3,4]
あなたの例のために。)
(ところで、再帰は実際にサイクルに崩壊したことに注意してください。)多くの比較が保存されているため、複雑さはクイックソートよりもいくらか優れています。
上記のコードには、smaller
必要かどうかの計算など、不必要な比較がいくつかありますが、簡単に削除できます。(ただし、遅延評価がそれを処理すると思います。)
アルゴリズムに問題はありません。もちろん、ほとんどの再帰アルゴリズムはループに変換できます。ここでは、再帰コードのループバージョンを示します。
function(T):
while minimum(T) <= lenght(T):
remove minimum(T) from T
loop
再帰アルゴリズムは、反復を使用するように書き換えることができます。結局のところ、チューリングマシンは再帰について何も知りませんが、任意のアルゴリズムを実装できます。原則として、独自のスタック操作コードを記述して、関数のパラメーターとそれが持つローカル変数の値を記憶することにより、再帰関数を書き換えることができます。この特定のケースでは、関数は末尾再帰であるため(再帰呼び出しが返されると、呼び出されたものもすぐに戻ります)、スタックを維持する必要さえありません。
配列全体をソートする必要がないため、min-heapを使用して部分ヒープソートを実行します。
指定されたしきい値を超えるまで、要素を貪欲にポップし続けます。