Algorithm 子集和问题实例

Algorithm 子集和问题实例,algorithm,computer-science,np-complete,Algorithm,Computer Science,Np Complete,我有一个问题,它是子集和问题的一个非常明显的例子: 给定[-6500065000]范围内的整数列表,如果列表的任何子集总和等于零,则函数返回true。否则返回False 我想问的更多的是一个解释,而不是一个解决方案 这是我在考虑问题的复杂性之前提出的一个特定于实例的解决方案 对数组A[]进行排序,并在排序期间将每个元素和到计数器“extSum”(O(NLogN)) 定义指针low=A[0]和high=A[n-1] 以下是决定代码: while(A[low]0){ while(sum-A[高]0

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

给定[-6500065000]范围内的整数列表,如果列表的任何子集总和等于零,则函数返回true。否则返回False

我想问的更多的是一个解释,而不是一个解决方案

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

  • 对数组A[]进行排序,并在排序期间将每个元素和到计数器“extSum”(O(NLogN))
  • 定义指针low=A[0]和high=A[n-1]
  • 以下是决定代码:
  • while(A[low]0){
    while(sum-A[高]0){
    总和=tmp;
    高--;
    }
    否则{
    高--;
    }
    }
    extSum-=A[低];
    低++;
    高=n-1;
    }
    否则{
    /*对称代码:开关低、高和操作>和<*/
    }
    }
    返回false;
    
首先,这个解决方案正确吗?我做了一些测试,但我不确定……看起来太容易了……
这段代码的时间复杂度不是O(n^2)吗

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

谢谢你的澄清


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

Hmm,我认为{0}会超过您的答案


因为它只会忽略while并返回false。

嗯,我认为{0}会超过你的答案



因为它只会忽略while并返回false。

如果我正确理解了您的代码,您不认为子集是连续的吗?这不一定是正确的case@isbadawi:嗯,我只是假设它会被排序,这是因为我将排序作为第一步。我的意思是,例如,如果你的输入是[-4,1,4],该怎么办。一个解决方案是{-4,4},但您不会找到it@isbadawi当前位置我想它确实找到了。。。如果输入为[-4,1,4],则extSum将为1。内部while的第一次运行将仅递减高(因为1-4<0),第二次运行将返回0:1-A[1]=0。。。。否?我只需要返回True或False,而不是实际的子集……如果我正确理解了您的代码,您不认为子集是连续的吗?这不一定是正确的case@isbadawi:嗯,我只是假设它会被排序,这是因为我将排序作为第一步。我的意思是,例如,如果你的输入是[-4,1,4],该怎么办。一个解决方案是{-4,4},但您不会找到it@isbadawi当前位置我想它确实找到了。。。如果输入为[-4,1,4],则extSum将为1。内部while的第一次运行将仅递减高(因为1-4<0),第二次运行将返回0:1-A[1]=0。。。。否?我只需要返回真或假,而不是实际的子集……嗯,是的,这是真的。但这是一个如此特殊的案例,我甚至没有提到。实际上,当我说“我知道我的方法可以改进很多”时,我想到的第一个优化是,当我对数组排序时,如果我找到任何0,我可以立即返回true。好吧,我认为如果你这样做,你就不必排序。考虑一个数组只保存负数和一个数组,只保存正和。你唯一要做的就是测试是否有一个和彼此相等。但它仍然是O(N^2),这里唯一的优点是不需要排序。可能是真的,但由于排序复杂度是O(NlogN),而DP复杂度更高,排序可能不是这里的瓶颈…对吗?这可能会失败{-4,-3,-2,6}?您只能使用一个数组。如果只有负数表示和加1,如果正数表示和加2,那么数组中等于3的数字就是你的答案。两个数组很容易给出这个想法。嗯,是的,这是真的。但这是一个如此特殊的案例,我甚至没有提到。实际上,当我说“我知道我的方法可以改进很多”时,我想到的第一个优化是,当我对数组排序时,如果我找到任何0,我可以立即返回true。好吧,我认为如果你这样做,你就不必排序。考虑一个数组只保存负数和一个数组,只保存正和。你唯一要做的就是测试是否有一个和彼此相等。但它仍然是O(N^2),这里唯一的优点是不需要排序。可能是真的,但由于排序复杂度是O(NlogN),而DP复杂度更高,排序可能不是这里的瓶颈…对吗?这可能会失败{-4,-3,-2,6}?您只能使用一个数组。如果只有负数表示和加1,如果正数表示和加2,那么数组中等于3的数字就是你的答案。两个数组很容易给出这个想法。
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;