【问题标题】:Instance of subset sum problem子集和问题的实例
【发布时间】:2011-09-15 15:12:52
【问题描述】:

我有一个问题,这是子集和问题的一个非常明显的例子:

“给定范围 [-65000,65000] 内的整数列表,如果列表的任何子集总和等于 0,则函数返回 true。否则返回 false。”

我想问的是解释而不是解决方案。

这是我在考虑问题的复杂性之前提出的一个特定于实例的解决方案。

  • 对数组 A[] 进行排序,并在排序期间将每个元素与计数器“extSum”相加 (O(NLogN))
  • 定义指针低 = A[0] 和高 = A[n-1]
  • 这里是决定代码:
  • while(A[low]<0){
      sum = extSum;
      if(extSum>0){
        while(sum - A[high] < sum){
            tmp = sum - A[high];
            if(tmp==0) return true;
            else if(tmp > 0){
                sum = tmp;
                high--;
            }
            else{
                high--;
            }
        }
        extSum -= A[low];
        low++;
        high = n - 1;
      }
      else{
        /* Symmetric code: switch low, high and the operation > and < */
      }
    }
    return false;
    

首先,这个解决方案是否正确?我做了一些测试,但我不确定……看起来太容易了……
这段代码的时间复杂度不是O(n^2)吗?

我已经阅读了各种 DP 解决方案,我想了解的是,对于我面临的问题的具体实例,它们比这种幼稚直观的解决方案要好得多。我知道我的方法可以改进很多,但在时间复杂度方面没有什么大不了的......

感谢您的澄清

编辑: 一个明显的优化是,在排序时,如果找到 0,该函数会立即返回 true....但这仅适用于其中有 0 的特定情况数组。

【问题讨论】:

  • 如果我正确理解你的代码,你不是假设子集是连续的吗?不一定是这种情况
  • @isbadawi:好吧,我只是假设它会被排序,这是因为我将它作为第一步进行排序。
  • 我的意思是例如如果您的输入是 [-4, 1, 4]。一个解决方案是 {-4, 4},但你不会找到它
  • @isbadawi:我认为它确实找到了...如果输入是 [-4,1,4],那么 extSum 将为 1。内部 while 的第一次运行只会递减高(因为 1 - 4
  • 我只需要返回 True 或 False,而不是实际的子集......

标签: algorithm computer-science np-complete


【解决方案1】:

嗯,我认为 {0} 会击败你的答案。

因为它会简单地忽略 while 并返回 false。

【讨论】:

  • 嗯,是的,这是真的。但这是一个如此具体的案例,我什至没有提到它。实际上,当我说“我知道我的方法可以改进很多”时,我想到的第一个优化是,当我对数组进行排序时,如果找到任何 0,我可以立即返回 true。
  • 好吧,我认为如果你做 dp 你不必排序。考虑一个数组只保存负数的总和,一个数组只保存正数的总和。唯一要做的就是测试是否有一个和彼此相等。但它仍然是 O(N^2),这里唯一的优点是你不需要排序。
  • 可能是真的,但是由于排序复杂度为 O(NlogN) 且 DP 复杂度更高,排序可能不是这里的瓶颈......对吧?
  • 好吧,这可能会失败{-4,-3,-2,6}?
  • 你只能使用一个数组。如果只有负数给你加 1 的总和,如果正数给你加 2 的总和,则数组中等于 3 的数字就是你的答案。两个数组很容易给出这个想法。
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多