问题描述
我想将n个元素的所有分区都分为k个子集,这是我基于递归公式的算法,用于查找所有Stirling second numbers
fun main(args: Array<String>) {
val s = mutableSetof(1,2,3,4,5)
val partitions = 3
val res = mutableSetof<MutableSet<MutableSet<Int>>>()
partition(s,partitions,res)
//println(res)
println("Second kind stirling number ${res.size}")
}
fun partition(inputSet: MutableSet<Int>,numOfPartitions: Int,result: MutableSet<MutableSet<MutableSet<Int>>>) {
if (inputSet.size == numOfPartitions) {
val sets = inputSet.map { mutableSetof(it) }.toMutableSet()
result.add(sets)
}
else if (numOfPartitions == 1) {
result.add(mutableSetof(inputSet))
}
else {
val popped: Int = inputSet.first().also { inputSet.remove(it) }
val r1 = mutableSetof<MutableSet<MutableSet<Int>>>()
partition(inputSet,numOfPartitions,r1) //add popped to each set in solution (all combinations)
for (solution in r1) {
for (set in solution) {
set.add(popped)
result.add(solution.map { it.toMutableSet() }.toMutableSet()) //deep copy
set.remove(popped)
}
}
val r2 = mutableSetof<MutableSet<MutableSet<Int>>>()
partition(inputSet,numOfPartitions - 1,r2) //popped is single elem set
r2.map { it.add(mutableSetof(popped)) }
r2.map { result.add(it) }
}
}
代码对于k = 2效果很好,但是对于更大的n和k,它会丢失一些分区,在这里我找不到错误。
示例:n = 5,k = 3输出
Second kind stirling number 19
的正确输出为25。
解决方法
如果您可以阅读Python代码,请考虑下一个算法,该算法已从我对set分区的实现中迅速适应为相等大小的部分。
递归函数用N个值填充K个零件。
lastfilled
参数有助于避免重复-它增加了每个零件中前导(最小)元素的顺序。
empty
参数旨在避免出现空零件。
def genp(parts:list,empty,n,k,m,lastfilled):
if m == n:
print(parts)
global c
c+=1
return
if n - m == empty:
start = k - empty
else:
start = 0
for i in range(start,min(k,lastfilled + 2)):
parts[i].append(m)
if len(parts[i]) == 1:
empty -= 1
genp(parts,m+1,max(i,lastfilled))
parts[i].pop()
if len(parts[i]) == 0:
empty += 1
def setkparts(n,k):
parts = [[] for _ in range(k)]
cnts = [0]*k
genp(parts,-1)
c = 0
setkparts(5,3)
#setkparts(7,5)
print(c)
[[0,1,2],[3],[4]]
[[0,3],[2],1],[2,4],[3]]
[[0,[3,4]]
[[0,2,[1],[1,[4]]
[[0],[3]]
[[0],3,[2]]
[[0,[2]]
[[0],3]]
[[0],4]]
25
,
不确定,代码中的确切问题是什么,但是以递归的方式查找所有斯特林第二个数字要简单得多:
value="1" <?= isset($_POST["grade"]) && $_POST["grade"] == "1" ? "checked" : "" ?>
,
我改进了 Kornel_S 的代码。 有一个 func 可以列出所有可能的组合。小心大数字:)
def Stirling2Iterate(List):
Result = []
def genp(parts:list,lastfilled):
if m == n:
nonlocal Result
nonlocal List
Result += [ [[List[item2] for item2 in item] for item in parts] ]
return
if n - m == empty: start = k - empty
else: start = 0
for i in range(start,lastfilled + 2)):
parts[i].append(m)
if len(parts[i]) == 1: empty -= 1
genp(parts,m + 1,lastfilled))
parts[i].pop()
if len(parts[i]) == 0: empty += 1
def setkparts(n,k):
parts = [ [] for _ in range(k) ]
cnts = [0] * k
genp(parts,-1)
for i in range(len(List)): setkparts(len(List),i + 1)
return Result
示例:
# EXAMPLE
print('\n'.join([f"{x}" for x in Stirling2Iterate(['A','B','X','Z'])]))
# OUTPUT
[['A','Z']]
[['A','X'],['Z']]
[['A','Z'],['X']]
[['A','B'],['X',['B']]
[['A',['B','X']]
[['A'],['X'],['B'],['Z']]
[['A'],['X']]
[['A'],'Z']]
[['A'],['Z']]