「ユニークサブセット生成」と呼ばれるものは、integer partitions with distinct partsとしてよく知られています。 Mathworldにはthe Q functionというエントリがあり、別個の部分を持つパーティションの数がカウントされます。
しかし、あなたの関数は少なくとも2つのの異なる部分にsequence that you linked in your questionパーティションの--the数を生成する、些細なパーティション(すなわちn -> (n)
)をカウントするので、あなたが探しているのは、実際にQ(n) - 1
ではありません。 This answerには数学に関する同様の質問には、より大きな値に簡単に適合させることができるn = 200
までのシーケンスを計算するためのJavaの効率的なアルゴリズムが含まれています。ここで
は、参照されたアルゴリズムの組み合わせの説明です:
は彼らの合計によってグループ化された{1, 2, 3}
のすべてのサブセットのテーブルで始まるのをしてみましょう:
index (sum) partitions count
0 () 1
1 (1) 1
2 (2) 1
3 (1+2), (3) 2
4 (1+3) 1
5 (2+3) 1
6 (1+2+3) 1
は、我々が構築したいとしサブテーブルのすべての新しいテーブル{1, 2, 3, 4}
。 {1, 2, 3}
のすべてのサブセットも{1, 2, 3, 4}
のサブセットであるため、上記の各サブセットは新しいテーブルに表示されます。実際には、新しいテーブルを等しいサイズの2つのカテゴリに分けることができます。ではなくであるサブセットには、4
が含まれます。私たちができることは、上記の表から始めて、それをコピーしてから、それを4
で "伸ばす"ことです。ここで{1, 2, 3, 4}
のためのテーブルです:
index (sum) partitions count
0 () 1
1 (1) 1
2 (2) 1
3 (1+2), (3) 2
4 (1+3), [4] 2
5 (2+3), [1+4] 2
6 (1+2+3),[2+4] 2
7 [1+2+4],[3+4] 2
8 [1+3+4] 1
9 [2+3+4] 1
10 [1+2+3+4] 1
4
が含まれるすべてのサブセットは、角括弧で囲まれて、それらは括弧で囲まれている古いサブセットの4
に正確に1を加えることによって形成されています。このプロセスを繰り返して{1,2,..,5}
、{1,2,..,6}
などの表を作成することができます。
実際にはサブセット/パーティションを格納する必要はありません。各インデックス/合計のカウントが必要です。たとえば、{1, 2, 3}
の表にカウントだけがある場合、{1, 2, 3, 4}
のカウント表を作成するには、index + 4
の現在のカウントにcount
を追加して、それぞれ(index, count)
のペアを古い表から取得します。考えられるのは、3
の合計である{1, 2, 3}
という2つのサブセットがある場合、これらの2つのサブセットのそれぞれに4
を追加すると、7
の2つの新しいサブセットが作成されるということです。 - ゼロに合計空set--
def c(n):
counts = [1]
for k in range(1, n + 1):
new_counts = counts[:] + [0]*k
for index, count in enumerate(counts):
new_counts[index + k] += count
counts = new_counts
return counts
我々はただ一つのサブセットを持つ{}
用のテーブル、で始まる:これを考慮して
が、ここでは、このプロセスのPython実装です。次に、
{1}
のテーブルを作成し、次に
{1, 2}
のテーブルを構築します。
{1,2,..,n}
まですべてのパーティションを
n
に数えます。
n
のパーティションには、
n
より大きい整数を含めることはできません。今
、我々はコードに2つの主要な最適化を行うことができます。
リミットテーブルをするだけでは、我々が興味を持っているすべてのだから、n
までのエントリを含めるindex + k
がn
を超えた場合、我々は。それを無視してください。各繰り返しで大きなテーブルを作成するのではなく、最終的なテーブルのスペースを事前に割り当てることもできます。
は、代わりに、我々は慎重に後方古いテーブルを反復処理する場合は、各反復でゼロから新しいテーブルを作成するのは、我々は実際に更新することができ、それインプレース新しい値のいずれかをめちゃくちゃにせずに。これらの最適化により
、あなたが効果的に機能を生成することにより、動機た先に参照されたthe Mathematics answerから同じアルゴリズムを、持っています。それはO(n^2)
時間で実行され、O(n)
スペースしかかかりません。 Pythonでどのように見えるかは次のとおりです。
def c(n):
counts = [1] + [0]*n
for k in range(1, n + 1):
for i in reversed(range(k, n + 1)):
counts[i] += counts[i - k]
return counts
def Q(n):
"-> the number of subsets of {1,..,n} that sum to n."
return c(n)[n]
def f(n):
"-> the number of subsets of {1,..,n} of size >= 2 that sum to n."
return Q(n) - 1
ありがとうございます。私はそれの背後にある数学を理解することにいくつかの困難を抱えています! – user5566364
@ user5566364私は同意したので、リンクされたアルゴリズムの説明を追加しました(関数の生成は含まれません)。長いことですが、それが助けてくれることを願っています。 –
ありがとうございました。 – user5566364