Python 在最坏的情况下,子集和算法比2^(n/2)快一点?

Python 在最坏的情况下,子集和算法比2^(n/2)快一点?,python,algorithm,complexity-theory,time-complexity,np,Python,Algorithm,Complexity Theory,Time Complexity,Np,在分析了在2^(n/2)时间内运行的最快子集求和算法后,我注意到可以进行一些轻微的优化。我不确定它是否真的算作优化,如果算作优化,我想知道它是否可以通过递归来改进 基本上来自原始算法:(参见标题为“指数时间算法”的部分) 它将列表拆分为两部分 然后,它在2^(n/2)时间内生成这两个的排序幂集 然后,它在两个列表中进行线性搜索,查看两个列表中的1个值是否使用巧妙的技巧求和为x 在我的优化版本中 它获取列表并删除最后一个元素last 然后它将列表一分为二 然后,它在2^((n-1)/2)时间

在分析了在2^(n/2)时间内运行的最快子集求和算法后,我注意到可以进行一些轻微的优化。我不确定它是否真的算作优化,如果算作优化,我想知道它是否可以通过递归来改进

基本上来自原始算法:(参见标题为“指数时间算法”的部分)

  • 它将列表拆分为两部分
  • 然后,它在2^(n/2)时间内生成这两个的排序幂集
  • 然后,它在两个列表中进行线性搜索,查看两个列表中的1个值是否使用巧妙的技巧求和为
    x
在我的优化版本中

  • 它获取列表并删除最后一个元素
    last
  • 然后它将列表一分为二
  • 然后,它在2^((n-1)/2)时间内生成这两个的排序幂集
  • 然后,它在两个列表中进行线性搜索,查看两个列表中的1个值是否与
    x
    x-last
    (同时使用相同的运行时间)相加
如果它找到了其中一个,那么我就知道它起作用了。我尝试使用python时间函数对大小为22的列表进行测试,我的版本的速度显然快了一倍

运行下面的代码后,它显示

0.050999879837   <- the original algorithm
0.0250000953674   <- my algorithm
这是我刚才用来生成powerset列表的助手库

def dec_to_bin(x):
    return int(bin(x)[2:])

def getNums(lst, xs):
    sums = []
    n = len(lst)
    for i in xs:
        bin = str(dec_to_bin(i))
        bin = (n-len(bin))*"0" + bin
        chosen_items = getList(bin, lst)
        sums.append(sum(chosen_items))
    sums.sort()
    return sums

def getList(binary, lst):
    s = []
    for i in range(len(binary)):
        if binary[i]=="1":
            s.append(float(lst[i]))
    return s
然后,它在2^((n-1)/2)时间内生成这两个的排序幂集

好的,因为现在列表少了一个元素。然而,这并不是什么大不了的事,它只是对
2^(1/2)
的持续时间改进

然后,它在两个列表中进行线性搜索,以查看两个列表中的1个值是否与x或x-last(在相同的时间和相同的运行时间)相加

。。。这一改进将会消失,因为现在你要做两倍的运算来检查x和x最后的和,而不是只检查x

我们可否不重复一遍又一遍


不,你不能,因为同样的原因,你不能一次又一次地分割原始算法。这个技巧只适用一次,因为一旦你开始在两个以上的列表中查找值,你就不能再使用排序技巧了。

如果不阅读wiki或你的代码2^((n-1)/2)=2^(n/2)/2^(1/2),即相同的渐近性能边界,那么显示我的版本的时间值会更快吗?既然你声称第二部分否定了第一部分的改进,那么最后的时间不应该与原始算法时间相同吗?@omega如果你说的是大O时间,你需要在不同的
n
上进行一系列的时间,才能说它比
2^(n/2)
好。单个计时结果可能只是一个恒定的时间改进。@omega线性搜索和子集和生成都是O(2N/2)-每次从末尾取下一个时,都会将子集和部分减少1/2^(1/2),并将线性搜索的数量增加一倍(增加2倍),从而使理论总时间增加约2^(1/2)-真实世界的速度提高可能是因为子集和比线性搜索只快一个常数因子
def dec_to_bin(x):
    return int(bin(x)[2:])

def getNums(lst, xs):
    sums = []
    n = len(lst)
    for i in xs:
        bin = str(dec_to_bin(i))
        bin = (n-len(bin))*"0" + bin
        chosen_items = getList(bin, lst)
        sums.append(sum(chosen_items))
    sums.sort()
    return sums

def getList(binary, lst):
    s = []
    for i in range(len(binary)):
        if binary[i]=="1":
            s.append(float(lst[i]))
    return s