最简单的方法是递归:
Make [[A]] list
Insert new item in all possible places -
before current sublists
between all sublists
after current sublists
into every sublist
例如,list [[B][A]] 生成 5 个带有项目 C 的新列表 - 插入 C 的位置是:
[ [B] [A] ]
^ ^ ^ ^ ^
三个二级列表[[A],[B]], [[B],[A]], [[A,B]]产生5+5+3=13个三级列表。
替代方式:
生成从 1...1 到 1..n 的所有 n 长度非递减序列,并为每个序列生成唯一的排列。
这些排列的值对应于每个项目的桶号。例如,122 序列给出了对应于分布的 3 个排列:
1 2 2 [1],[2, 3]
2 1 2 [2],[1, 3]
2 2 1 [3],[1, 2]
在任何情况下,分布的数量都会迅速增加(有序的贝尔号码1, 3, 13, 75, 541, 4683, 47293, 545835, 7087261, 102247563...)
在 Delphi 中实现迭代方法(在ideone 上与 FP 兼容的完整代码)
procedure GenDistributions(N: Integer);
var
seq, t, i, mx: Integer;
Data: array of Byte;
Dist: TBytes2D;
begin
SetLength(Data, N);
//there are n-1 places for incrementing
//so 2^(n-1) possible sequences
for seq := 0 to 1 shl (N - 1) - 1 do begin
t := seq;
mx := 0;
Data[0] := mx;
for i := 1 to N - 1 do begin
mx := mx + (t and 1); //check for the lowest bit
Data[i] := mx;
t := t shr 1;
end;
//here Data contains nondecreasing sequence 0..mx, increment is 0 or 1
//Data[i] corresponds to the number of sublist which item i belongs to
repeat
Dist := nil;
SetLength(Dist, mx + 1); // reset result array into [][][] state
for i := 0 to N - 1 do
Dist[Data[i]] := Dist[Data[i]] + [i]; //add item to calculated sublist
PrintOut(Dist);
until not NextPerm(Data); //generates next permutation if possible
end;
现在是 Python 递归实现 (ideone)
import copy
cnt = 0
def ModifySublist(Ls, idx, value):
res = copy.deepcopy(Ls)
res[idx].append(value)
return res
def InsertSublist(Ls, idx, value):
res = copy.deepcopy(Ls)
res.insert(idx, [value])
return res
def GenDists(AList, Level, Limit):
global cnt
if (Level==Limit):
print( AList)
cnt += 1
else:
for i in range(len(AList)):
GenDists(ModifySublist(AList, i, Level), Level + 1, Limit)
GenDists(InsertSublist(AList, i, Level), Level + 1, Limit)
GenDists(InsertSublist(AList, len(AList), Level), Level + 1, Limit)
GenDists([], 0, 3)
print(cnt)
编辑:@mhmnn 在JavaScript 中克隆了这段代码,使用自定义项进行输出。