在子集和

时间:2015-10-31 23:41:14

标签: python recursion subset-sum

我有以下算法递归地解决子集求和问题:

def findSubset(alist, targ, i, sumsofar):
    if sumsofar == targ:
        return True
    if i == len(alist):
        return False
    inc = findSubset(alist, targ, i+1, sumsofar+alist[i])
    noninc = findSubset(alist, targ, i+1, sumsofar)
    return inc or noninc

该算法工作正常,但它只给出一个布尔答案。所以,如果我这样称呼它:

alist = [4, 6, 21, 29, 37, 50]
findSubset(alist, 76, 0, 0)
>>> True

但我希望它返回[4, 6, 29, 37]

这是我改变算法的尝试:

def findSubset(alist, targ, i, sumsofar, new):
    if sumsofar == targ:
        return new
    if i == len(alist):
        return []
    inc = findSubset(alist, targ, i+1, sumsofar+alist[i], new.append(alist[i]))
    noninc = findSubset(alist, targ, i+1, sumsofar, new)
    return inc or noninc

使用它的地方:

alist = [4, 6, 21, 29, 37, 50]
findSubset(alist, 76, 0, 0, [])
>>>AttributeError: 'NoneType' object has no attribute 'append'

我必须做些什么来使其发挥作用,甚至可能?

2 个答案:

答案 0 :(得分:1)

我的以下代码有效:

def findSubset(alist, targ, i, sumsofar, listsofar):
    if sumsofar == targ:
        return True, listsofar
    if i == len(alist):
        return False, listsofar
    inc, inclistsofar = findSubset(alist, targ, i+1, sumsofar+alist[i], listsofar + [alist[i]])
    noninc, noninclistsofar = findSubset(alist, targ, i+1, sumsofar, listsofar)

    if inc:
        return inc, inclistsofar
    else:
        return noninc, noninclistsofar

alist = [4, 6, 21, 29, 37, 50]
print findSubset(alist, 76, 0, 0, [])

list.append()是一个就地操作。它返回None类型,但您需要将列表作为参数传递。

答案 1 :(得分:0)

李恒峰解决方案的改进。使用默认参数可以在没有零和空列表的情况下进行更好的调用find_subset(alist, 76)

def find_subset(alist, targ, i=0, sumsofar=0, listsofar=None):
    if listsofar is None:
        listsofar = []
    if sumsofar == targ:
        return True, listsofar
    if i == len(alist):
        return False, listsofar
    inc, inclistsofar = find_subset(alist, targ, i+1, sumsofar + alist[i], listsofar + [alist[i]])
    noninc, noninclistsofar = find_subset(alist, targ, i+1, sumsofar, listsofar)

    if inc:
        return inc, inclistsofar
    else:
        return noninc, noninclistsofar

alist = [4, 6, 21, 29, 37, 50]
print(find_subset(alist, 76))

<强>更新

根据Blckknght的评论进一步改进:

def find_subset(alist, targ, i=0, sumsofar=0, listsofar=None):
    if listsofar is None:
        listsofar = []
    if sumsofar == targ:
        return listsofar
    if i == len(alist):
        return None
    inclistsofar = find_subset(alist, targ, i+1, sumsofar + alist[i], 
                               listsofar + [alist[i]])
    if inclistsofar:
        return inclistsofar
    else:
        noninclistsofar = find_subset(alist, targ, i+1, sumsofar, listsofar)
        return noninclistsofar

alist = [4, 6, 21, 29, 37, 50]
print(find_subset(alist, 76))
print(find_subset(alist, 100))
print(find_subset(alist, 1000))
print(find_subset(alist, 4))
print(find_subset(alist, 17))

输出:

[4, 6, 29, 37]
[21, 29, 50]
None
[4]
None