【问题标题】:How to iterate through all cases when partitioning objects分区对象时如何遍历所有情况
【发布时间】:2014-11-22 22:43:16
【问题描述】:

假设我有 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 还是递归都没有关系,但它必须相当有效。

【问题讨论】:

  • 您可以使用 for 循环或递归,for 是一个常数 n,而递归您必须通过递归来计算时间复杂度
  • 伪代码会很好:)
  • 那么到目前为止你尝试过什么?我不是来为你做你的工作的。
  • 在编写两个嵌套递归函数定义后卡住了。如果我知道该怎么做就不会问问题了...
  • 能否请您也发布您的尝试,它必须是递归的吗?可以在for中吗?还是您在寻找最高效的?

标签: algorithm iteration


【解决方案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)

【讨论】:

    猜你喜欢
    • 2012-08-08
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 2021-11-01
    • 2021-01-27
    • 2016-11-13
    • 2014-11-23
    • 2013-11-04
    相关资源
    最近更新 更多