要素の最大のセットを見つける方法


14

アルゴリズムに問題があります。

TnSTaSa|S|

例えば:

  1. 場合 = [1、3、4、1、3、6]、その後、、[3,3]、[6]又は[3、4、6]又は[4、3、6]とすることができます。STS
  2. で = [7,5、1、1,7、4]、次いで [7、5,7、4]です。STS

この再帰関数を試しました。

function(T):
    if minimum(T) >= length(T): 
        return T
    else: 
        return function(T\minimum(T))

非再帰的なアルゴリズムはありますか?(再帰アルゴリズムをチェックしなかったため、いくつかの欠陥がある可能性があります。)

回答:


14

Tを並べ替えます。次に、要素を取得しT[i] >= i+1ます。

たとえばsorted(T)=[6,4,3,3,1,1]。その後、T[0] = 6 > 1T[1] = 4 > 2T[2] = 3 <= 3そして最後に、T[3] = 3 < 4私たちは持っているのでS = [T[0], T[1], T[2]]


3
これは、当然のことながら、他の溶液ミス、それはOPが探していた表示任意のではなく、溶液全ての溶液。{633}
リックデッカー

2
要素の数を正しく取得します。3つの要素を備えたソリューションがありますが、4つではありません。この場合、3つ以上の4つの要素があるので、3つを選択して解を求めることができます。
-gnasher729

3
正当性の議論を感謝します。
ラファエル

おそらくintroselectのバリアントを使用して、O(n)時間でそれを行うことができると思います。
user2357112は、Monicaを

8

私の元々のコメントから:これは、学術生産性評価における遍在する量であるHirshインデックスと密接に関連しています。これは -indexhとして知られています。要するに、それぞれが少なくともhの引用(そのようなhの最大のもの)を持つようなの出版物の数として定義されます。hhh

あなたの問題が異なる唯一の方法は、基準を満たす出版物の数だけでなく、それらの引用カウントが何であるかに興味があるということです、それは些細な修正です。データはすでにそこにあり、元のアルゴリズムはそれをドロップします。

一般的に実行される計算はかなり簡単で、カロリス・ジュオデルの答えに同意します

更新:データのサイズと文字に応じて、ピボットポイントの上下のデータをフィルター処理して配列を部分的に並べ替える方法を検討する価値があります(クイックソートが思い浮かびます)。次に、ピボットが少なすぎるか多すぎるかによって、ピボットを調整し、それを含むサブセットで再実行します。より高い要素間の順序は必要ありません。また、それより低い要素間の順序は確かに必要ありません。したがって、たとえば、h 1以上のすべての要素が見つかり、それらの要素がh 1未満になったら、そのサブセットに再度触れる必要はなく、追加するだけです。これは、クイックソートに固有の再帰変換末尾再帰ので、ループのように書き換えることができるが。hh1h1

私の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、結果に間違いなく参加することがわかっているものを収集し、それ以上ソートしないことです。はめあいgreaterx合わせれば幸運です。さもなければ、より小さいサブセットで試す必要があります。(ピボットxは、現在考慮されているサブリストの最初の項目であるものです。)最大の要素を1つずつ取得することに対する大きな利点は、平均サイズブロックでこれを行うことです。g / 2で、さらに並べ替える必要はありません。remanng/2

例:

セットを取りましょう[1,3,4,1,3,6]

  1. x = 1granted = []greater = [3,4,1,3,6]smaller最初のステップでピボットが小さすぎる(実際には非常に小さいため空になっている)場合、病理学的なケースにぶつかります。幸いなことに、私たちのアルゴリズムはその準備ができています。破棄xして、greater単独で再試行します。

  2. x = 3granted = []greater = [4,3,6]。一緒に、それらは長さ4の配列を形成しますが、下から3だけに制限されているため、多すぎます。greater単独で繰り返します。

  3. x = 4granted = []greater = [6]。これにより、それぞれ4以上の2つの要素の配列が得られ、さらにいくつかの要素に使用できる可能性があります。これを保持し、繰り返しsmaller = [3]ます。

  4. x = 3granted = [4,6]greater = []。これにより、それぞれ3つ以上の3つの要素の配列が得られるため、解決策が得られ[3,4,6]、戻ることができます。(順列は、入力の順序によって異なりますが、常に決して、可能な限り最高の条件が含まれていないことに注意してください[3,3,6]または[3,3,4]あなたの例のために。)

(ところで、再帰は実際にサイクルに崩壊したことに注意してください。)多くの比較が保存されているため、複雑さはクイックソートよりもいくらか優れています。

n1

OログnOn

nOn2

上記のコードには、smaller必要かどうかの計算など、不必要な比較がいくつかありますが、簡単に削除できます。(ただし、遅延評価がそれを処理すると思います。)


6

アルゴリズムに問題はありません。もちろん、ほとんどの再帰アルゴリズムはループに変換できます。ここでは、再帰コードのループバージョンを示します。

function(T):
    while minimum(T) <= lenght(T):
         remove minimum(T) from T
    loop

6
すべての再帰アルゴリズムはループに変換できます。結局のところ、チューリングマシンは再帰について何も知りません。
デビッドリチャービー

4

再帰アルゴリズムは、反復を使用するように書き換えることができます。結局のところ、チューリングマシンは再帰について何も知りませんが、任意のアルゴリズムを実装できます。原則として、独自のスタック操作コードを記述して、関数のパラメーターとそれが持つローカル変数の値を記憶することにより、再帰関数を書き換えることができます。この特定のケースでは、関数は末尾再帰であるため(再帰呼び出しが返されると、呼び出されたものもすぐに戻ります)、スタックを維持する必要さえありません。


3

配列全体をソートする必要がないため、min-heapを使用して部分ヒープソートを実行します。

指定されたしきい値を超えるまで、要素を貪欲にポップし続けます。


2
ここでも、正確さのアイデアをいただければ幸いです。
ラファエル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.