如何在分区对象时迭代所有情况

时间:2014-11-22 22:43:16

标签: algorithm iteration

假设我有k个相同的项目,我想将它们分成n组。如何迭代每一种可能的组合?

到目前为止,我已在电路板上写了一些数字。假设k = n = 4,那么系统地列出它们的方法是找到所有4位数字(其中0可以是数字),其数字加起来为k。按升序排列:

0 0 0 4
0 0 1 3
0 0 2 2
0 0 3 1
0 0 4 0
0 1 0 3
0 1 1 2
0 1 2 1
0 1 3 0
0 2 0 2
0 2 1 1
0 2 2 0
0 3 0 1
0 3 1 0
0 4 0 0
1 0 0 3
...

我希望避免在不考虑总和的情况下首先生成所有组合,然后删除所有不加k的组合。由于这将产生k ^ n个组合,并且可能需要很长时间。如果它是for或recursion并不重要,但它必须合理有效。

1 个答案:

答案 0 :(得分:1)

我设法通过递归和循环的组合找到了解决方案。

这里是伪代码(我不知道如何编写伪代码......我用[a; b; c ...]表示列表:

// Returns a list of integers in range [0, k].
function num_list k =
...


// Recursively generate all the possible partitions with [total] objects
// and [groups] partitions. Returns a list of list of integers.
function generate (int groups, int total) = {
    if (groups == 1) then {
        return [[total]];
    } else {
        int list nums = num_list total;
        // looping through all values for one of the partitions.
        int list list list container1;
        foreach (i in nums) {
            // recursive step - generate all combinations without the first 
            // partition
            int list list subset = generate (groups - 1) (total - i);
            // append the first partition onto each element of this list
            int list list container2 = [];
            foreach (l in subset) {
                container2.add(l.prepend i);
            }
            container1.add container2;
        }
        // Flatten just takes a list of lists, and extract everything in each
        // list and mesh everything together.
        return container1.flatten();
}

这是python中的代码:

# Recursively generate all the possible partitions with [total] objects
# and [groups] partitions. Returns a list of list of integers.
def generate (groups, total):
    if (groups == 1):
        return [[total]];
    else:
        nums = range(total + 1);
        # looping through all values for one of the partitions.
        container1 = [];
        for i in nums:
            # recursive step - generate all combinations without the first 
            # partition
            subset = generate (groups - 1, total - i);
            # append the first partition onto each element of this list
            container2 = [];
            for l in subset:
                container2 += [([i] + l)];
            container1 += [container2];
        # Flatten just takes a list of lists, and extract everything in each
        # list and mesh everything together.
        return [item for sublist in container1 for item in sublist];

以下是......函数式编程语言ocaml中的代码:

(* Returns a list of integers in range [0, k]. *)
let num_list n : int list =
  let rec helper num =
    if num = 0 then
      [0]
    else
      num :: (helper (num - 1)) in
  List.rev (helper n)

(**
 * Recursively generate all the combinations when dividing total number of
 * objects among groups.
 *)
let rec generate groups total : int list list =
  (* generate all the possible *)
  match groups, total with
  | 1, t -> [[t]]
  | g, t -> 
    let nums = num_list t in
    (* looping through all values for the head group *)
    let helper e : int list list =
      let subset = generate (g - 1) (t - e) in
      (* appending in front of every single result from generate *)
      List.map (fun l -> e :: l) subset in
    List.flatten (List.map helper nums)