【问题标题】:Python3.6, trying to append to a attribute list during recursive backtracking, but it discards results?Python3.6,在递归回溯期间尝试附加到属性列表,但它会丢弃结果?
【发布时间】:2020-07-17 20:46:31
【问题描述】:

我正在尝试使用递归回溯生成所有唯一子集。 (面试准备)。 问题陈述是:给定一组不同的整数 nums,返回所有可能的子集(幂集)。注意:解集不能包含重复的子集。

不过,对于输入 [1,2,3],我的输出是:

[[],[],[1],[1,2],[1],[],[2],[]]

当答案应该是:

[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

不过,当我打印出要附加到列表中的内容时,它会打印出正确的答案:

[1]
[1, 2]
[1, 2, 3]
[1, 3]
[2]
[2, 3]
[3]

我认为递归传递这些列表、重用它们等可能是个问题,所以我复制了参数。出于某种原因,我还必须在我的参数上运行一个副本。

我是否缺少对这些数据结构的内存管理的理解?在将这种方法用于其他回溯问题时,我也遇到了同样的问题。

class Solution:
    def __init__(self):
        self.subset = [[]]

    def subsets(self, nums: List[int]) -> List[List[int]]:
        self.initSubsets(nums,[])
        return self.subset

    def initSubsets(self,options,currentSubset):
        frameOptions = options.copy()
        frameCurrentSubset = currentSubset.copy()

        for option in options:
            # add option to subset
            frameCurrentSubset.append(option)
            # add to solution
            self.subset.append(frameCurrentSubset)
            print(frameCurrentSubset)
            # guarentee no dups
            frameOptions.remove(option)
            # recurse
            self.initSubsets(frameOptions,frameCurrentSubset)
            # undo changes
            frameCurrentSubset.remove(option)

        return

【问题讨论】:

    标签: python-3.x recursion backtracking


    【解决方案1】:

    我认为你的问题出在这一行:

    self.subset.append(frameCurrentSubset)
    

    您将列表附加到列表但稍后您

    frameCurrentSubset.remove(option)
    

    frameCurrentSubset 中删除元素的位置。但问题在于,这样做还会从复制到 self.subset 的列表中删除该元素,因为它与内存中的列表相同。

    解决办法是改用:

    self.subset.append(frameCurrentSubset[:])
    

    这将附加一个新列表,其中包含当时frameCurrentSubset 的所有元素。

    一个完整的解决方案是:

    from typing import List
    
    class Solution:
        def __init__(self):
            self.subset = [[]]
    
        def subsets(self, nums: List[int]) -> List[List[int]]:
            self.initSubsets(nums,[])
            return self.subset
    
        def initSubsets(self,options,currentSubset):
            frameOptions = options.copy()
            frameCurrentSubset = currentSubset.copy()
    
            for option in options:
                # add option to subset
                frameCurrentSubset.append(option)
                # add to solution
                self.subset.append(frameCurrentSubset[:])
                print(frameCurrentSubset)
                # guarentee no dups
                frameOptions.remove(option)
                # recurse
                self.initSubsets(frameOptions,frameCurrentSubset)
                # undo changes
                frameCurrentSubset.remove(option)
    
            return
    
    example = Solution()
    result = example.subsets([1, 2, 3])
    print(result)
    

    【讨论】:

    • 那么它实际上是通过引用而不是通过值传递它吗?
    • 列表包含引用而不是值(因为在 Python 中一切都是对象)。
    猜你喜欢
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多