【发布时间】:2013-11-25 14:56:00
【问题描述】:
给定一个列表,并输出其所有排列的列表。
这是我的想法:
递归地,hd::tl 的排列是将hd 分配到tl 的每个排列列表中。通过分发hd,我的意思是将hd 插入到列表中每个可能的插槽中。
例如,将1 分配到[2;3] 会生成[[1;2;3];[2;1;3];[2;3;1]]。
这里是代码
let distribute c l =
let rec insert acc1 acc2 = function
| [] -> acc2
| hd::tl ->
insert (hd::acc1) ((List.rev_append acc1 (hd::c::tl)) :: acc2) tl
in
insert [] [c::l] l
let rec permutation = function
| [] -> [[]]
| hd::tl ->
List.fold_left (fun acc x -> List.rev_append (distribute hd x) acc) [] (permutation tl)
我猜上面的代码是正确的。
我的问题是:有没有更好的方法(在简单性、性能、空间效率等方面)在 OCaml 中编写排列?
【问题讨论】:
-
不是 [1;2;3] 的所有排列都是 [1;2;3],[1;3;2],[2;1;3],[2;3 ;1],[3;1;2],[3;2;1] ?
-
@aneccodeal 是的。请注意我给出的示例仅适用于
distribute,不适用于permutation -
如果您关心性能,您可以直接为递归底部附近的小列表编写结果。如果您想要中等大小的列表的排列,您可以将结果重新编码为流而不是列表。 (实际上,您无法获得列表的所有排列长度超过 13 或 14。)
-
@JeffreyScofield 你在谈论惰性列表吗?如果是这样,我认为这是一个很好的观点。你能从中得出一个答案吗?
-
是的,惰性列表。我认为,懒惰地生成排列是一个挑战。我看看能不能解决。
标签: algorithm functional-programming ocaml permutation