【发布时间】:2012-11-30 19:02:21
【问题描述】:
如何找到整数列表的所有分区?大多数情况下我需要使用递归的算法,因为我将在 SML 中实现它。我只需要算法,我会自己做编码部分。我错误地编写了查找子集的代码,我没有太多时间来做这个
SML 有点类似于帕斯卡,所以你会掌握我要用阶乘编写的格式,例如这个有趣的 fuc x = if x
提前致谢
【问题讨论】:
标签: algorithm recursion sml ml partition-problem
如何找到整数列表的所有分区?大多数情况下我需要使用递归的算法,因为我将在 SML 中实现它。我只需要算法,我会自己做编码部分。我错误地编写了查找子集的代码,我没有太多时间来做这个
SML 有点类似于帕斯卡,所以你会掌握我要用阶乘编写的格式,例如这个有趣的 fuc x = if x
提前致谢
【问题讨论】:
标签: algorithm recursion sml ml partition-problem
The partition problem 是一个已知的NP-Hard 问题(因此没有已知的多项式解决方案),可以使用用递归很好地编写的穷举搜索来解决。
伪代码(尝试做类似ML的伪代码,希望对您有所帮助和清晰):
partition([],A,B): #base clause
if (sum(A) == sum(B)):
print (A,B) # this is a partition
partition(list, A,B):
e <- head(list)
partition(tail(list),e :: A,B)
partition(tail(list),A, e :: B)
(如果我没记错e :: A是在ML中在A的开头添加一个元素,如果我记错了,请随时纠正)
【讨论】:
查看finding all the subsets。基本上在每次置换迭代中,您可以通过从当前子集的并集中减去整个集合来获得分区的另一部分。
【讨论】:
如果你有一个集合S{S<sub>1</sub>,...,S<sub>n</sub>}的k-partitions,比如{P<sub>1</sub>,...,P<sub>k</sub>},你可以生成kk-partitions of S &Union; {S<sub>n+1</sub>}:
{P<sub>1</sub>,..., P<sub>i-1</sub>, P<sub>i</sub> &Union; {n+1}, P<sub>i+1</sub>,... P<sub>k</sub>} 用于 {1...k} 中的 i
加上(k+1)-分区P &Union; {k+1}
调用这些从P 生成的分区。很容易证明,从{1,...,n} 的两个不同分区生成的所有分区集都是不相交的,并且{1,...,n+1} 的每个分区都是从{1,...,n} 的某个分区生成的。
我认为这足以使问题的递归解决方案显而易见。
为了验证,{1,...,n} 的分区数是B(n),其中B 是贝尔数,(Sloane A000110)
【讨论】:
从您对amit的回复来看,您似乎在寻找:
fun partitions [] = []
| partitions [x] = [[[x]]]
| partitions (x::xs) =
let
val zsss = partitions xs
in
map (fn zss => [x]::zss) zsss @
map (fn zs::zss => (x::zs)::zss) zsss
end
编辑:抱歉,我将您之前的示例误读为partition [1,2,3] = [[[1,2,3]],[[1],[2,3]],[[1,2],[3]],[[1],[2],[3]]],即有序分区。
这是您实际问题的解决方案(我认为):
fun extensions x [] = []
| extensions x (xs::xss) =
((x::xs)::xss) :: map (fn zss => xs::zss) (extensions x xss)
fun partitions [] = [[]]
| partitions (x::xs) =
List.concat (map (fn zss => ([x]::zss) :: extensions x zss) (partitions xs))
【讨论】: