【问题标题】:Partition of set {1, 2, 3, ... N}集合 {1, 2, 3, ... N} 的分区
【发布时间】:2015-03-10 18:14:50
【问题描述】:

给定子集 {1, 2, 3, .... N}。我必须找到一组从 1 到 N 的所有整数可以划分为两个总和相等的子集的方法数。

什么都没有想到。我想尝试“蛮力搜索”,但它可以限制时间。有什么快速算法吗?

【问题讨论】:

  • 当您有一种特别简单的方法来定义整数序列时,您可能会尝试计算前几个值,然后自己识别它们或将它们输入整数序列在线百科全书。 oeis.org/…

标签: c++ algorithm


【解决方案1】:

它可以在多项式时间内计算为从 1 到 n 的 (1 + x^k) 乘积中的 x^(n(n+1)/4) 的系数。有几种评估产品的方法;将术语一一相乘就足够了。

【讨论】:

  • 不错。特别是如果 n(n+1) 不是 4 的倍数,则答案为 0,无需计算系数。
【解决方案2】:

我认为这个问题是 NP 难题,所以我认为您无法在多项式时间内找到最优解(除非 P=NP)。

编辑: 是的,正如我的继任者指出的那样,我在谈论更一般的集合二分问题,应该有一种简单的方法来找出每个可能的集合对。

【讨论】:

    【解决方案3】:

    我不知道是否有纯粹的数学方法来解决这个问题,或者一些超级奇特的方法......但我的第一直觉是,既然你知道这些数字是连续的,那么在列表中的任何位置你都应该是能够说出到目前为止的总和是什么。因此,如果您选择对许多不应该出现的排列进行暴力破解,那么您应该能够做出一些明智的选择,以消除很多您需要检查的情况。

    【讨论】:

      【解决方案4】:

      分解问题...

      想象一下,您只想找到总和为一个值的 2 个数字的子集。显然你可以在线性时间内做到这一点。例如,如果集合是 { 1, 2, 4, 7, 9 } 并且值为 11,那么从一端 (1) 开始,您从另一端倒退到 9(不匹配)。因此,现在您将底部数字索引增加一 (=2),它匹配 9。再次增加 (=4)。等等。这样做你只需要让 ONE 通过值列表。

      当然,这只解决了问题的 2 成员子集部分。

      所以,现在对 3 成员子集重复该过程。您可以使用完全相同的技术,除了使用 3 个游标而不是 2 个。依此类推...

      我不知道作为游标数量函数的复杂性,它可能是 log N,但无论如何它都会比蛮力搜索快得多。如果是 log N,那么总复杂度就是 N log N,其中 N 是集合中元素的个数。

      【讨论】:

      • 这与暴力搜索有何不同?
      • @DouglasZare 你了解第一种情况(2 个数字的组合)如何是线性的,以及它与尝试 2 个数字的每个组合之间的区别吗?例如,对于给定一组 5 个值的只有 2 个数字的情况,蛮力需要 5x4/2 = 10 次测试,但我描述的算法只需要 3 次测试,它是次线性的。
      • 100个对象中选择50个对象的方式数和2^100个相差不大,能查到最后一个对象是否在列表中,最多能省下吗? n 因子,通常是 2 因子,偏离算法的指数性质?我还是叫它蛮力。有更好的方法,例如分而治之(2^(n/2) 容易)或动态规划(n^3 或更好)。
      猜你喜欢
      • 2012-07-30
      • 2010-12-02
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-10
      • 2013-06-19
      相关资源
      最近更新 更多