递归测验 - 无法解决

时间:2013-10-18 00:47:32

标签: python recursion

今天我的CPSC教授在python中分配了一个测验,主题是递归。

整个班级都陷入了第二个问题,这是下面的问题。没有人能够接近解决方案。

def sub_set(A):
    if A == []: return A
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += _____
    return _____

示例代码:

print(sub_set([1, 2]))    # [[], [1], [2], [1, 2]]
print(sub_set([1, 2, 3])) # [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

您只能修改下划线,例如下面的示例可能会演示。

我的解决方案远非如此接近,甚至不应该考虑:

def sub_set(A):
    if A == []: return A
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += _____
    return result + [A[:1]] + [A] + [A[::2]]

#sub_set([1, 2, 3]) -> [[3], [3], [3], [2], [2, 3], [2], [1], [1, 2, 3], [1, 3]]

有谁知道如何解决这个问题?当我们只有15分钟的时间来解决它时,这似乎是一个非常具有挑战性的问题。

仅供参考,他说如果考虑到班上没有人 - 大约10名精心挑选的学生的高级综合课程 - 可以解决这个问题,他会放弃这个问题。

7 个答案:

答案 0 :(得分:14)

我认为问题中存在一个错误。递归的基本情况是错误的。

空集的所有子集的集合不是空集,而是包含空集的集合。

def sub_set(A):
    if A == []: return A

应该是

def sub_set(A):
    if A == []: return [A]

已添加:使用该补丁,这是一个解决方案:

def sub_set(A):
    if A == []: return [A]
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += [L, A[0:1] + L]
    return result

答案 1 :(得分:3)

如果没有一些重大的hackery,我不相信这是可以解决的,因为基本情况是错误的。对于[],应该有一个子集:[]本身。但是return A会返回 no 子集。

因此,您需要执行A[:1] + L,而不仅仅是执行[A[:1] + L]。而且,您必须A[:1] + X + result而不是[A[:1]] + X + result。所以:

def sub_set(A):
    if A == []: return A
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += [A[:1] + L]
    return [A[:1]] + X + result

这仍然会留下子列中的空列表。解决这个问题的唯一方法是这样的愚蠢:

    return ([] if [] in X + result else [[]]) + [A[:1]] + X + result

这将至少返回正确的值...但顺序错误,并且所有单元素子集的副本。如果你愿意,你可以进一步扩展hackiness;我不认为这是值得的。

答案 2 :(得分:2)

def sub_set(A):
    if A == []: return A
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += [L, [A[0]]+L]
    return [[A[0]]] + result

print sub_set([1, 2])
>> [[1], [2], [1, 2]]
print sub_set([1, 2, 3])
>> [[1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

答案 3 :(得分:1)

def sub_set(A):
    if A == []: return A
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += [L, A[0:1] + L]
    return result if X != [] else [[], A[0:1]]

这与noa's回答基本相同,减去您不应编辑的代码部分的更改。

答案 4 :(得分:0)

X是不包含A[0]的所有子集的集合。这意味着他们也在subset(A)。缺少的是包含A[0]的所有子集,您可以通过将A[0]添加到X中的每个元素来获得。

所以你的第一个空白是A[0] + L

你的第二个是result + X

答案 5 :(得分:0)

不是您正在寻找的解决方案,但这是一个使用yield的工作解决方案:)

def powerset(A):
    if A:
        for L in powerset(A[1:]):
            yield L
            yield A[:1] + L
    else:
        yield []

答案 6 :(得分:0)

这是一个可能的解决方案。它返回正确的值,但不一定按相同的顺序:

def sub_set(A):
    if A == []: return A
    X = sub_set(A[1:])
    result = []
    for L in X:
        result += [ A[:1] +L ]
    return [[]] + X[1:] + (result or [A[:1]])

有效的是,对于每一层,我们将原始列表分成两部分:初始项和列表的其余部分。我们得到列表其余部分的所有子集,将第一个项目附加到每个部分,前置一个[],然后返回它。

示例流程:

[1,2,3] -> A0 = [1], A1X =[2,3] ->
    [2,3] -> A0 = [2], A1X = [3] ->
        [3] -> A0 = [3], A1X = [] ->
            [] -> return []
        [3] * [] = []. return [ [], [3] ]
    [2] * [[], [3]] = [[2], [2,3]]. return [ [] + [[3]] + [[2], [2,3]] ]
[1] * [ [], [3], [2], [2,3] ] = [[1], [1,3], [1,2], [1, 2, 3] ]
             return [ [] + [[], [3], [2], [2,3]] + [[1], [1,3], [1,2], [1,2,3]]

一般流程为[] + A0 * [子集] + [子集]。要注意的问题是子集本身始终以[]开头 - 所以如果不删除它,你将得到它两次,并确保在A0已经存在时不会复制A0(如[A0] + [] == [A0],你在列表中总是有[A0]),但是在第一次迭代(返回[]之后)你必须特别包含它。