今天我的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名精心挑选的学生的高级综合课程 - 可以解决这个问题,他会放弃这个问题。
答案 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]),但是在第一次迭代(返回[]之后)你必须特别包含它。