O(k)の配列で最小のk要素を見つける


12

これは私がウェブで見つけた興味深い質問です。n個の数値(それらに関する情報なし)を含む配列が与えられた場合、配列1を与えられたときにO(k)時間でk個の最小要素を返すことができるように、線形時間で配列を前処理する必要があります<= n

私は何人かの友人とこの問題について議論してきましたが、誰も解決策を見つけることができませんでした。助けていただければ幸いです!

クイックノート:-k個の最小要素の順序は重要ではありません-配列内の要素はnumberであり、整数である場合もあり、そうでない場合もあります(したがって、基数ソートなし)-数kは前処理段階ではわかりません。前処理はO(n)時間です。O(k)timeの関数(k個の最小要素を見つける)。


4
最小ヒープの使用はどうですか?
Shir

1
k-skybandとtop-kの計算を見てください。論文cs.sfu.ca/~jpei/publications/subsky_tkde07.pdfには、関連文献の素晴らしいレビューがあります。
アンドラスサラモン

1
Shir-Iはmin-heapアイデアを調べました。ただし、最小ヒープのk個の最小数を印刷するためには、O(klogn)時間であり、必要に応じてO(k)ではありません
イダン

4
@idannik:なぜ、最小ヒープのk個の最小要素を見つけるのに時間かかると思いますか?Ω(klogn)k
クリストファーアーンスフェルトハンセン

8
これは研究レベルではないと思います。割り当てのように見えます。どこで見つけたの?
カベ

回答:


24

時間O n 値の配列を前処理します。nO(n)

  • in
  • 一方、i>2
    • 時間O i におけるA [ 1 .. i ]の中央値を計算しますmA[1..i]O(i)
    • A [ 1 .. i / 2 1 ]に分割するA[1..i] A [ I / 2 + 1 ... I ] M同じ時間です。A[1..i/21]mA[i/2+1..i]m
    • ii/2

合計事前計算時間はO(1+2+4+...+n)O(n)

時間O k Aの最小要素のクエリに答えます。kAO(k)

  • llog2k
  • 選択番目の要素XA [ 2 リットル.2 l + 1(k2l)x時間における O 2 LO K A[2l..2l+1]O(2l)O(k)
  • パーティションによって X同じ時間にA[2l..2l+1]x

含ま k個の最小要素。A[1..k]k

参照:

  • 1999年、DorとZwickは、2.942 n + o n )の比較内で要素の中央値を計算するアルゴリズムを提供しました。これにより、kを選択するアルゴリズムが生成されます。n2.942n+o(n)kから番目の要素を未満で順序付けられていない要素6つのNの比較。n6n

1
Iは、外側ループが'に私のためのものになっている推測 '。あなたのアルゴリズムは、ユヴァル・フィルマスの答えとは異なりますか?{2lgn,,4,2,1}
ラドゥグリゴール

2
これは、アルゴリズムを任意の一般化したものです。また、私の回答から(意図的に)省略されたいくつかの実装の詳細も説明します。n
ユヴァルフィルマス

3
@YuvalFilmusあなたのコメントで、私の答えがあなたのものに非倫理的に近いことを暗示したいですか?これは、私が質問を検討したときに思いついた解決策です。あなたが似たようなものを投稿したのを見ましたが、それが不明瞭であることがわかったので、私は自分で書きました(あなたの大規模な編集とは対照的に)。最終的に重要なのは、実際に誰が書いたのかではなく、システム上の回答の品質です。バッジと評判は単なるインセンティブであり、それ自体の目的ではありません。
ジェレミー

4
@ジェレミーまったくありません。ちょうど2つの解決策が同じである(しかし、あなたの任意の)こと、そしてそれが実際に宿題の質問である場合に備えて詳細を具体化しなかったことだけです。n
ユヴァルフィルマス

2
ああ:(その場合は申し訳ありません。(完全な答えを与えることは、割り当ての疑いよりも優先されると思いますが)
ジェレミー

14

簡単にするために、と仮定します。位置での要素を見つけるために、線形時間の選択アルゴリズムを使用して2 m個- 12 m個- 22 m個- 3... 1。これには直線的な時間がかかります。所与のkは、検索tはそのようなことは2 T - 1K 2 T。なお、2 トン2 k個。ランクのすべての要素を最大2 t除外するn=2m2m1,2m2,2m3,,1kt2t1k2t2t2k2t、線形時間選択アルゴリズムを使用して、時間O 2 t= Oの位置にある要素を見つけますkO(2t)=O(k)

明確化:前処理に時間がかかる注意しないと実際にそうなります。前処理を線形時間で行う方法は次のとおりです。Θ(nlogn)

while n > 0:
  find the (lower) median m of A[0..n-1]
  partition A in-place so that A[n/2-1] = m
  n = n/2

インプレースパーティショニングは、クイックソートのように行われます。実行時間はで線形であるため、線形です。最終的に、配列Aは次の特性を満たします。各kに対してA [ 0 .. n / 2 k1 ]n / 2 k個の最小要素で構成されます。n+n/2+n/4++1<2nAkA[0..n/2k1]n/2k


1
当然。配列が並べ替えられている場合、前処理なしでこれをで解決できます。おそらく、時間O n k番目に大きい要素を見つけることができる線形時間選択アルゴリズムを知らないのでしょうか?O(1)kO(n)
ユヴァルフィルマス

4
@Yuval Filmus:合計n log nステップ、n回アルゴリズム実行していませんか?それとも、何らかのインターリーブを念頭に置いていましたか?lognnlogn
アンドラスサラモン

3
@AndrásSalamon:Jeremyからの回答(これは私とほとんど同じように見えます)を読むと、最初にアレイ全体を処理し、次に前半を処理することがわかります。
ラドゥグリゴール

3
@AndrásSalamonラドゥは正しいです。中央値を見つけたら、アレイを(インプレースで)下半分と上半分に分割し、下半分を再帰します。実行時間は、比例します。n+n/2+n/4++1<2n
ユヴァルフィルマス

5
:ちなみにこのアルゴリズムは、以前の質問に対する私の答えのサブルーチンとして表示されますcstheory.stackexchange.com/questions/17378/...
デイビット・エップスタイン

2

最初にO(n)を使用して、最小ヒープを構築します。O(k)を使用して、最小ヒープのk最小要素を見つけることができることが知られています。

Frederickson、Greg N.最小ヒープでの選択に最適なアルゴリズム、Inf。計算します。104、No. 2、197-214(1993)。ZBL0818.68065 ..


1
I don't see how we can extract the smallest k elements from a min-heap in time O(k), as removing each element takes logarithmic time in the size of the heap. Could you clarify what you had in mind here? Thanks!
a3nm

@a3nm It is indeed not a simple algorithm, but I've updated the reference.
hqztrue

Sorry, as far as I can tell the reference that you added just talks about selecting the k-th smallest element (i.e., a single element, not the k smallest elements) in time O(k). I don't see how this would adapt to extracting the k smallest elements. Could you maybe explain or update the reference?
a3nm

@a3nm yes the reference only gives you the k-th smallest element x. However after knowing that, you can just perform a dfs in the heap to find all elements <x in O(k).
hqztrue

Sorry I don't see which DFS you would perform to find these elements? (Some of them may not be ancestors of the k-th smallest element in the heap, i.e., as far as I can tell locating, e.g., the k/2-th element knowing the position of the k-th element is not trivial.)
a3nm

0

Use linear time selection to find the kth largest element, then do a partition step from quicksort using the kth largest element as the pivot.


1
The original question mentions that k is not known at preprocessing time....
Jeremy

2
I see. My mistake.
jbapple
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.