【问题标题】:My recursive solution in Python is appending and replacing all current items in answer list with the current list我在 Python 中的递归解决方案是用当前列表追加和替换答案列表中的所有当前项目
【发布时间】:2016-12-08 12:31:46
【问题描述】:

我正在尝试针对编程问题实施 Python 解决方案 查找整数数组中的所有子集。我应该返回一个数组 包含整数数组的所有子集,没有重复项和 排序。

def subsetHelper(cur_set, index, A, ans):
    if index >= len(A):
        print "appending ", cur_set
        ans.append(cur_set)
        print "ans: ", ans
        return
    # don't include current number
    subsetHelper(cur_set, index+1, A, ans)

    # include current number
    cur_set.append(A[index])
    subsetHelper(cur_set, index+1, A, ans)
    cur_set.pop()

def subsets(A):
    A.sort()
    ans = []
    cur_set = []
    # dont include current number
    subsetHelper(cur_set, 0, A, ans)
    return ans

在 C++ 中实现相同的逻辑会产生正确的返回值。但是,当我在 Python 中执行此操作时,我得到的只是最后的空列表集合,而在迭代期间,它会将相同的当前列表复制到列表中的所有项目,即使打印输出显示它每次都附加正确的子集.为什么会这样?这是输出:

print subsets([1,2,3])
appending  []
ans:  [[]]
appending  [3]
ans:  [[3], [3]]
appending  [2]
ans:  [[2], [2], [2]]
appending  [2, 3]
ans:  [[2, 3], [2, 3], [2, 3], [2, 3]]
appending  [1]
ans:  [[1], [1], [1], [1], [1]]
appending  [1, 3]
ans:  [[1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]
appending  [1, 2]
ans:  [[1, 2], [1, 2], [1, 2], [1, 2], [1, 2], [1, 2], [1, 2]]
appending  [1, 2, 3]
ans:  [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[], [], [], [], [], [], [], []]

【问题讨论】:

  • 我真的不明白你为什么要把这门课。除了传递相同参数的方法之外,您没有实例属性。无论如何,问题在于您传递的是同一个列表,而不是复制。也就是说,您正在建立一个对同一列表的引用列表!每次附加 cur_list 时,它都是同一个列表对象。这就是为什么当每次对subsetHelper 的递归调用到达最后一行时最终弹出所有内容时,您最终会得到一个空列表列表。
  • 能否请您提供用于获取此输出的完整代码? (即您如何称呼Solution)。
  • 不要使用它,但它可以(就像 itertools 一样)来测试你的实现:def subsets(L): return sorted([[L[j] for j in range(len(L)) if 1 << j & i] for i in range(2**len(L))]) :)
  • 对不起,我完全搞砸了我的帖子。新的编辑显示了我原来的问题应该是什么样子。此外,我完全意识到拥有解决方案类毫无意义,我只是在一个名为interviewbit.com 的准备网站上复制我在控制台上编写的代码,其中样板代码具有您应该实现的解决方案方法在解决方案类内部。对于所有这些错误,我深表歉意,我会在以后尝试校对我的帖子。

标签: python list


【解决方案1】:

这里有两个问题:第一个问题是你ans.extend而不是ans.append,一旦改变我们得到第二个问题,最后是空列表,原因是append只添加到列表中ans 对 cur_set 的引用,您最终会在递归过程中删除所有元素,因此您最终会获得对同一列表的多个引用,该列表最后为空,要解决此问题,您只需附加一个副本以list(cur_set) 表示列表的当前内容。

也没有理由把它变成一个类

def subsetHelper(cur_set, index, A, ans):
    if index >= len(A):
        print "appending ", cur_set
        ans.append(list(cur_set))  # <--- here was the problem
        print "ans: ", ans
        return
    # don't include current number
    subsetHelper(cur_set, index+1, A, ans)

    # include current number
    cur_set.append(A[index])
    self.subsetHelper(cur_set, index+1, A, ans)
    cur_set.pop()

def subsets(A):
    A.sort()
    ans = []
    cur_set = []
    # dont include current number
    subsetHelper(cur_set, 0, A, ans)
    return ans

测试

>>> subsets([1,2,3])
appending  []
ans:  [[]]
appending  [3]
ans:  [[], [3]]
appending  [2]
ans:  [[], [3], [2]]
appending  [2, 3]
ans:  [[], [3], [2], [2, 3]]
appending  [1]
ans:  [[], [3], [2], [2, 3], [1]]
appending  [1, 3]
ans:  [[], [3], [2], [2, 3], [1], [1, 3]]
appending  [1, 2]
ans:  [[], [3], [2], [2, 3], [1], [1, 3], [1, 2]]
appending  [1, 2, 3]
ans:  [[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
>>> 

【讨论】:

  • 就是这样!以及其他 cmets。谢谢大家!
【解决方案2】:

问题是您在调用之间重复使用 cur_set 列表对象,所以即使在 cur_set 已添加到 ans 之后,对 susetHelper 的未来调用仍会修改列表,特别是未来对 cur_set.pop() 的调用清空列表。您可以通过存储cur_set 的副本而不是确切的对象来解决此问题。

def subsetHelper(cur_set, index, A, ans):
    if index >= len(A):
        print "appending ", cur_set
        ans.append(cur_set[:])
        print "ans: ", ans
        return
    # don't include current number
    subsetHelper(cur_set, index+1, A, ans)

    # include current number
    cur_set.append(A[index])
    subsetHelper(cur_set, index+1, A, ans)
    cur_set.pop()

def subsets(A):
    A.sort()
    ans = []
    cur_set = []
    # dont include current number
    subsetHelper(cur_set, 0, A, ans)
    return ans

print subsets([12, 13])

并不是说您在这里混合了基于状态的 oop 和函数式编程风格。原则上这并没有错,但是调试基于状态的递归可能非常令人沮丧。如果这是一个学习练习,我建议您首先尝试以纯函数方式(递归方式)解决此问题,然后以纯基于状态的方式再次执行此操作。两种方式都可以让您更好地理解问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 2015-08-22
    • 1970-01-01
    相关资源
    最近更新 更多