【问题标题】:How to find all ways to obtain an integer n as the sum of m integers (without order)?如何找到所有方法来获得一个整数 n 作为 m 个整数的总和(无序)?
【发布时间】:2017-01-24 19:34:24
【问题描述】:

我正在寻找一种算法,它可以找到将整数 n 表示为 m(非负)整数之和的所有方法。我对 m=6 和 n⩽20 特别感兴趣。找到所有可能性的最快方法是什么(使用计算机,而不是手动)。如果可能的话,我只想看看六个整数的组合,顺序不相关(即 [1, 2, 0, 0, 0, 0] 和 [2, 1, 0, 0, 0, 0 ] 计为 1 个组合)。

最简单的方法是简单地尝试所有小于或等于 20 的 6 个整数的排列,然后只将总和为 20 的排列添加到我们的结果中(如果我们不想查看排序,则删除双精度数) .然而,这似乎需要很长时间,因为要检查 20^6 种可能性需要相当长的时间。

解决这个问题的更有效方法是什么?

【问题讨论】:

  • 提示:如果您按排序顺序生成重复,则可以轻松避免重复。如果你有 m 个数字要填写,它们总和为 n,并且数字按升序排列,那么第一个数字的可能性是什么?

标签: algorithm number-theory


【解决方案1】:

您可以通过以单调递增的顺序生成数字来避免重复(每个数字等于或大于前一个数字)。

对于给定的count(例如 6),您可以递归地定义问题,方法是生成第一个数字的所有可能值,然后递归地生成所有 count - 1 数字列表,总和为原始总和减去第一个数字,第一个数字是列表中剩余数字的最小值。

因为数字需要增加,所以您不能“过早达到峰值” - 您可以通过将总和除以计数来计算最大值(因为所有剩余值都必须等于或大于此值) .

这是一个简单的Java实现:

public static void outputSums(String start, int sum, int count, int min)
{
    // if there is just one value, it's just the sum:
    if(count == 1)
    {
        System.out.println(start + " " + sum);
        return;
    }

    int max = sum / count;  // calculate maximum value
    for(int i = min; i <= max; i++)
    {
        outputSums(start + " " + i,  // append each number to the list
            sum - i,  // recursively find numbers that sum to the remainder
            count - 1,   // with a count of one less
            i);   // equal to or greater to this one (i.e. increasing order)
    }
}

start 包含您目前输出的部分列表。当你第一次调用函数时它会是空的。

Demo

【讨论】:

    【解决方案2】:

    与前面的方法相反,是从大到小计算。

    这是一个 Python 实现,它使用迭代器,以便以编程方式使用。

    def partition (count, total, maximum = None) :
        if maximum is None or total < maximum:
            maximum = total
        if 0 == count:
            yield []
        else:
            while total <= count * maximum:
                for part in partition(count - 1, total - maximum, maximum):
                    yield part + [maximum]
                maximum = maximum - 1
    

    下面是一个如何以编程方式使用它来打印输出的示例:

    for part in partition(6, 10):
        print(part)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 2011-02-08
      • 2021-06-14
      • 2012-01-01
      • 2014-09-10
      • 1970-01-01
      • 2020-12-18
      相关资源
      最近更新 更多