web-dev-qa-db-ja.com

固定サブセットサイズの合計サブセット

部分和問題 状態:

整数のセットが与えられた場合、合計がゼロである空でないサブセットはありますか?

この問題は一般にNP完全です。このわずかな変種の複雑さがわかっているかどうか、私は興味があります。

整数のセットが与えられた場合、合計がゼロであるサイズkのサブセットはありますか?

たとえば、_k = 1_の場合、バイナリ検索を実行してO(log n)で答えを見つけることができます。 _k = 2_の場合、それをO(n log n)に下げることができます(たとえば、 合計が指定された数に等しい配列から要素のペアを検索する を参照してください)。 _k = 3_の場合、O(n^2)を実行できます(たとえば、 指定された数値に合計が最も近い配列内の3つの要素を検索する を参照)。

kの関数としてこの問題に設定できる既知の境界はありますか?

動機として、私はこの質問について考えていました 配列を2つの部分に分割して、2つの部分が同じ平均になるようにするにはどうすればよいですか? 、それが実際にNP完全かどうかを判断しようとしました答えは、上記のような式があるかどうかにあります。

一般的なソリューションを除いて、私は_k=4_の最適な境界を知ることに非常に興味があります。

30
PengOne

k = 4の場合、空間複雑度O(n)、時間複雑度O(n2 * log(n))

配列を並べ替えます。 2つの最小要素と2つの最大要素から始めて、2つの要素のすべてのlesser合計_(a[i] + a[j])_を降順で計算し、2つの要素のすべてのgreater合計_(a[k] + a[l])_を計算します。増加しない順序。合計がゼロ未満の場合はlesser合計を増やし、合計がゼロより大きい場合はgreaterを減らし、合計がゼロ(成功)または_a[i] + a[j] > a[k] + a[l]_(失敗)の場合は停止します。 。

コツは、すべてのインデックスijをこのような方法で反復することで、_(a[i] + a[j])_は決して減少しません。また、klの場合、_(a[k] + a[l])_は決して増加しないはずです。優先キューはこれを行うのに役立ちます:

  1. key=(a[i] + a[j]), value=(i = 0, j = 1)を優先キューに入れます。
  2. 優先キューから_(sum, i, j)_をポップします。
  3. 上記のアルゴリズムではsumを使用します。
  4. _(a[i+1] + a[j]), i+1, j_および_(a[i] + a[j+1]), i, j+1_は、これらの要素がまだ使用されていない場合にのみ優先キューに入れてください。使用された要素を追跡するには、各「i」に対して最大使用された「j」の配列を維持します。 'i'よりも大きい 'j'の値のみを使用するだけで十分です。
  5. 手順2から続行します。

k> 4の場合

スペースの複雑さがO(n)に制限されている場合、_k-4_値にブルートフォースを使用し、残りの_4_値に上記のアルゴリズムを使用するよりも優れた方法はありません。時間計算量O(n(k-2) * log(n))。

非常に大きいk整数線形計画法 の場合、ある程度の改善が見られる場合があります。

更新

nが非常に大きい場合(最大整数値と同じオーダー)、O(1)優先度キューを実装して、O(n)の複雑さを改善することができます。2)およびO(n(k-2))。

_n >= k * INT_MAX_の場合、O(n)スペースの複雑さを伴う別のアルゴリズムが可能です。_k/2_値のすべての可能な合計のビットセットを事前計算し、それを使用しての合計をチェックします。他の_k/2_値。時間計算量はO(n(ceil(k/2)))。

13
Evgeny Kluev

W + X + Y + Z = {w + x + y + z | 0で0かどうかを判断する問題Wのw、Xのx、Yのy、Zのz}は、煩わしい退化したケースがないことを除いて、基本的に同じです(つまり、問題は最小限のリソースで相互に削減できます)。

この問題(したがって、k = 4の元の問題)には、O(n ^ 2 log n)時間、O(n)空間アルゴリズムがあります。 k = 2のO(n log n)時間アルゴリズム(A + Bの0かどうかを判断するため)は、ソートされた順序でAにアクセスし、逆にソートされた順序でBにアクセスします。したがって、必要なのはA = W + XのO(n)空間イテレータであり、B = Y + Zに対して対称的に再利用できます。W= {w1、...、wn}をソートされた順序で使用します。 X内のすべてのxについて、Key-Valueアイテム(w1 + x、(1、x))を優先度付きキューに挿入します。 min要素(wi + x、(i、x))を繰り返し削除し、(wi + 1 + x、(i + 1、x))を挿入します。

4
Gina

非常によく似た質問:

サブセット和問題のこのバリアントは解決が簡単ですか?

それはまだNP完全です。

そうでない場合、サブセット和もPになります。これは、F(1) | F(2) | ... F(n)として表すことができるためです。ここで、Fは関数です。これにはO(O(F(1)) + O(F(2)) + O(F(n)))が含まれますが、これはまだ多項式ですが、NP完全であることがわかっているため正しくありません。

入力に特定の境界がある場合は、多項式時間を達成できることに注意してください。

また、総当たりの実行時間は二項係数で計算できることにも注意してください。

2
Pubby

O(n ^ 2log(n))のk = 4の解

ステップ1:ペアごとの合計を計算し、リストを並べ替えます。 n(n-1)/ 2の合計があります。したがって、複雑さはO(n ^ 2log(n))です。合計を作る個人のアイデンティティを保管してください。

ステップ2:上記のリストの各要素について、補集合を検索し、それらが「個人」を共有していないことを確認します。n^ 2の検索があり、それぞれが複雑さO(log(n))です。

編集:元のアルゴリズムの空間の複雑さはO(n ^ 2)です。仮想2D行列(配列のソートされたバージョンを格納するスペースを考慮する場合はO(n))をシミュレートすることにより、スペースの複雑さをO(1)に減らすことができます)。

最初に2D行列について:数値を並べ替え、ペアワイズ合計を使用して行列Xを作成します。これで、マトリックスは、すべての行と列がソートされるようになりました。この行列の値を検索するには、対角線上の数値を検索します。数値がX [i、i]とX [i + 1、i + 1]の間にある場合は、基本的に、行列X [i:N、0:i]とX [0:iに検索スペースを半分にすることができます。 、i:N]。結果の検索アルゴリズムはO(log ^ 2n)です(私はよくわかりません。誰かがそれをチェックできますか?)。

ここで、実際の行列を使用する代わりに、X [i、j]が事前に計算されるのではなく、必要に応じて計算される仮想行列を使用します。

結果として生じる時間計算量:O((nlogn)^ 2)。

PS:次のリンクでは、2Dソートされたマトリックス検索の複雑さはO(n)複雑さです。それが真の場合(つまり、O(log ^ 2n)が正しくない場合)、最後に、複雑さはO(n ^ 3)です。

2
ElKamina

時間計算量は自明にO(n^k)k要素からのnサイズのサブセットの数)です。

kは与えられた定数であるため、(おそらく非常に高次の)多項式の上限はnの関数として複雑さを制限します。

1
awesomo

Awesomoの答えに基づいて構築するために...数値がソートされていると仮定できる場合、与えられたkに対してO(n ^ k)よりもうまくいくことができます。サイズ(k-1)のすべてのO(n ^(k-1))サブセットを取得し、残りの数をバイナリ検索して、最初の(k-1)に追加するとターゲットになります。これはO(n ^(k-1)log n)です。これは、複雑さが確かにそれよりも少ないことを意味します。

実際、k = 3の場合の複雑度がO(n ^ 2)であることがわかっている場合、k> 3の場合はさらに良い結果が得られます。O(n ^()のあるすべての(k-3)サブセットを選択しますk-3))、そして残りの要素のO(n ^ 2)の問題を解きます。これは、k> = 3の場合はO(n ^(k-1))です。

しかし、多分あなたはもっとうまくやることができますか?これについて考えます。

編集:私は当初、この問題について別の見方を提案する多くのことを追加するつもりでしたが、要約版を投稿することにしました。他のポスターに、このアイデアにメリットがあると信じているかどうかを確認することをお勧めします。分析は難しいですが、それはうまくいくのに十分クレイジーかもしれません。

Kが固定されており、奇数と偶数の合計が特定の方法で動作するという事実を使用して、この問題を解決するための再帰的アルゴリズムを定義できます。

最初に、リストに偶数と奇数の両方が含まれるように問題を修正します(これは、すべてが偶数の場合は2で除算するか、すべてが奇数の場合は数値から1を、対象の合計からkを引くことで実現できます。必要に応じて)。

次に、偶数の奇数を使用することによってのみ偶数の目標合計に到達でき、奇数の奇数を使用するだけで奇数の目標合計に到達できるという事実を使用します。奇数の適切なサブセットを生成し、偶数を使用してアルゴリズムを再帰的に呼び出します。合計から調査対象の奇数のサブセットの合計を差し引き、kから奇数のサブセットのサイズを差し引きます。 k = 1の場合、二分探索を行います。 k> n(これが発生する可能性があるかどうか不明)の場合は、falseを返します。

奇数が非常に少ない場合は、これにより、勝者のサブセットの一部である必要がある用語をすばやく選択したり、そうでない用語を破棄したりできます。減算トリックを使用すると、多数の偶数の問題を多数の奇数の同等の問題に変換できます。したがって、最悪のケースは、偶数と奇数の数が非常に似ている場合であるに違いありません...そしてそれが私が今いるところです。これの無駄に緩い上限は、ブルートフォースよりも何桁も悪いですが、これはおそらくブルートフォースと同じくらい良いと思います。考えは大歓迎です!

EDIT2:説明のための上記の例。

{1, 2, 2, 6, 7, 7, 20}, k = 3, sum = 20.
Subset {}:
 {2, 2, 6, 20}, k = 3, sum = 20
 = {1, 1, 3, 10}, k = 3, sum = 10
 Subset {}:
  {10}, k = 3, sum = 10
  Failure
 Subset {1, 1}:
  {10}, k = 1, sum = 8
  Failure
 Subset {1, 3}:
  {10}, k = 1, sum = 6
  Failure
Subset {1, 7}:
 {2, 2, 6, 20}, k = 1, sum = 12
 Failure
Subset {7, 7}:
 {2, 2, 6, 20}, k = 1, sum = 6
 Success
1
Patrick87