2つの大きなセット間のセットの差の計算


14

整数と 2つの大きなセットがあります。各セットには約100万のエントリがあり、各エントリは最大10桁の正の整数です。 BAB

およびを計算する最適なアルゴリズムは何ですか?つまり、ないのエントリのリストを効率的に計算するにはどうすればよいですか?これらの操作を効率的にするために、これら2つのセットを表すのに最適なデータ構造は何でしょうか?B A A BABBAAB

私が思いつく最良の方法は、これらの2つのセットをソート済みリストとして保存し、のすべての要素をすべての要素と線形に比較することです。もっと良くできますか?BAB


別の方法で保存する場合は、より良い結果が得られる可能性があります。
リアルツスロー

また、結果を暗黙的なデータ構造として取得したい場合。2つのセットにクエリを実行して、独自のクエリのそれぞれに答えるような構造を作成できます。
リアルツスロー

1
@ user917279 1つの大きなポイントは、通常、前処理/構築時間、クエリ時間、メモリ使用量を相互にトレードオフできることです。構造体はめったに編集しませんが、多くのクエリを実行しますか?逆に?記憶は心配ですか?そのような質問は、実用的な観点から答えることができ、「正しい」「理論的な」構成の選択を知らせます。
ラファエル

1
@Raphaelより多くのメモリを使用したり、準備に時間を費やしたりすることで、(複雑さの点で)密集的に永続的なセットよりも優れた方法を提案できるでしょうか。あなたがそれが可能であると思うなら、私はただ興味があります。このサイズの入力セットのオプションとしてルックアップテーブルが表示されません。
smossen

1
@ user917279同一の2つの巨大なセットの例を考慮すると、ハッシュ構造を使用して作成されたデータ構造は、O(1)での等価性テストをサポートします。コンフルエントに永続的なセットは、2つの構造がほぼ等しい場合にもハッシュコンシングを利用します。複雑さは、これまでに順序付きセットで見た中で最高です。
smossen

回答:


9

特殊なデータ構造にセットを保存したい場合は、興味深い複雑さを得ることができます。

ましょう=O|A||B||AB|

その後、それぞれ集合演算およびを実行でき予想時間。したがって、本質的には、2つのセットの最小サイズ、または対称差のサイズのいずれか小さい方を取得します。対称差が小さい場合、これは線形よりも優れています。すなわち。大きな交差点がある場合。実際、必要な2つの差集合演算の場合、対称差のサイズを一緒に構成するため、これは実質的に出力に依存します。A Δ B O 私はログイン| A | + | B |ABABABABOログ|A|+|B|

詳細については、Olle LiljenzinによるConfluently Persistent Sets and Maps(2013)を参照してください。


論文のトレジャーは、順序付けられた検索ツリーです。私はそれらをソートされていないデータ構造として数えません。
smossen

@smossenは十分に真実です、私はそれを編集しました。
リアルツスロー

6

セットが並べ替えられたリンクリストとして表されている場合、線形スキャンは、私が行う方法を知っている最高の方法です。実行時間はです。O|A|+|B|

のすべての要素をすべての要素とペアで比較する必要はないことに注意してください。それは実行時間につながりますが、これはさらに悪いことです。代わりに、これら2つのセットの対称差を計算するために、mergesortの「マージ」操作に似た手法を使用して、両方のセットに共通する値を省略するように適切に変更できます。ABO|A|×|B|

より詳細には、次のような再帰アルゴリズムを構築して、とが値がソートされたリンクリストとして表されると仮定して、を計算できます。ABAB

difference(A, B):
    if len(B)=0:
        return A # return the leftover list
    if len(A)=0:
        return B # return the leftover list
    if A[0] < B[0]:
        return [A[0]] + difference(A[1:], B)
    elsif A[0] = B[0]:
        return difference(A[1:], B[1:])  # omit the common element
    else:
        return [B[0]] + difference(A, B[1:])

これを擬似Pythonで表現しました。あなたは、Pythonを読んでいない場合は、A[0]リンクリストの先頭でAA[1:]リストの残りの部分で、+リストの連結を表します。効率上の理由から、Pythonで作業している場合、おそらく上記のように正確に実装することは望ましくありません(たとえば、多くの一時リストを作成しないようにジェネレーターを使用した方がよい場合があります)アイデアを可能な限りシンプルな形で示します。この擬似コードの目的は、具体的な実装を提案することではなく、アルゴリズムを説明することだけです。

セットが並べ替えられたリストとして表され、出力が並べ替えられたリストとして提供されるようにしたい場合、これ以上良いことはできないと思います。基本的に、とすべての要素を調べる必要があります。正当化の非公式スケッチ:あなたはそれが両方に存在している知っている場合は、要素を見て省略することができる唯一のケースがあるので、あなたは、あなたがそれを出力することはできませんが、見ていないことをすべての要素がある場合にはと、しかし、その値を見ていなかった場合、どうしてそれが存在することを知ることができますか?ABAB


素晴らしい、セットがソートされたリストとして保存されるという制約が取り除かれた場合、他のオプションがありますか?
user917279

2

AとBのサイズが等しく、互いに素でインターリーブされている場合(Aの奇数とBの偶数など)、線形時間でのアイテムのペアワイズ比較はおそらく最適です。

AとBにAまたはBのどちらか、または両方にあるアイテムのブロックが含まれている場合、サブ線形時間でセットの差、結合、および交差を計算することができます。例として、AとBが正確に1つのアイテムで異なる場合、その差はO(log n)で計算できます。

http://arxiv.org/abs/1301.3388


1
彼は、セットが順序付けられていると言います。それは、それらがリスト、検索ツリー、または何か他のものとして保存されることを意味するかもしれません。データをリストとして保存する必要がある場合、線形時間でリストをスキャンするよりもアルゴリズムが優れていない場合、「ABを計算するための最適なアルゴリズム」を求めるのはまったく面白くない(既にアルゴリズムを見つけた)。
smossen

1
まあ、あなたは私と同じ論文をリンクしました(私はあなたと同じです)...次回あなたのリンクに名前を付けます:D
Realz Slaw

@smossen素晴らしい、私が持っているどんな知識(?)にも、私はそれらをソートされたリストとして表現しましたが、他の提案も謙虚に歓迎します。
ユーザー917279

2

nABab¯ab


1010

1
R.、ポイントを見逃しています。シングルlongは32個の要素または1、8個の要素を保存できbyteます。そのため、1Mエントリは最大125KのRAMにしか保存できません。ストレージは、問題の実装方法に応じて、他の表現よりも大幅に効率的になる可能性があります
...-vzn

そのため、OPが関心を持っているセットには12MB以上必要です。これはすべてのキャッシュを(現在)吹き飛ばし、スパースセットにとっては恐ろしいことです。特に、空のセットを作成すると、他のすべての操作が優先されます(スパースセットの場合)。ちなみに、KnuthはTAoCPでこの問題に対処しています。
ラファエル

12MB?え?ポスターには、彼には2セットしかないという。ポスターは、彼のセットのスパース性/密度を指定しませんでした。これは私の答えで指摘されています。彼はまばらなセットを持っていると仮定していますか?正解は1つもありません。このアプローチは、状況に応じて役立つ代替オプションとして指摘されています。この文脈ではめったに使用されません
...-vzn

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