【问题标题】:Why get different results, when using list.pop() and list = list[:-1] in recursive problem为什么在递归问题中使用 list.pop() 和 list = list[:-1] 会得到不同的结果
【发布时间】:2020-11-05 06:12:11
【问题描述】:

我正在尝试使用递归的方法来解决 Leetcode 上的"Combination Sum" 问题。

组合和问题

  1. 给定一个不同整数数组candidates和一个目标整数target,返回所有唯一组合的列表@ 987654325@其中所选数字的总和为 target您可以按任何顺序返回组合。
  2. 相同数字可以从candidates中选择无限次。如果至少一个所选数字的频率不同,则两个组合是唯一的。 示例
Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]

当我使用 "c = c[:-1]" 去除 "c" 的结尾元素时,我无法得到正确的结果。但是,在我将“c = c[:-1]”替换为“c.pop()”之后,结果就正确了。

看完this post,我的理解是

  1. "list.pop()" 将对原始列表进行更改,而"list[:-1]" 将创建一个新列表。
  2. “list.pop()”和“list=list[:-1]”会得到相同的结果

但在我的递归方法中,显然“list=list[:-1]”并没有完成工作。我想知道为什么递归函数中的“list.pop”和“list=list[:-1]”之间存在差异。为什么list=list[:-1]会在递归方法中出错?

这是我的代码:

"""
def findCombination(self, nums: List[int], target: int,
                    index: int, c: List[int],
                    res: List[List[int]]):
"""
def findCombination(nums, target, index, c, res):
    if target <= 0:
        if target == 0:
            res.append(c.copy())
        return
    for i in range(index, len(nums)):
        if nums[i] > target:
            break
        c.append(nums[i])
        print(f"self.findCombination({nums}, {target - nums[i]}, {i}, {c}, {res})")
        findCombination(nums, target - nums[i], i, c, res)
        c.pop()
        # c = c[:-1]

if __name__ == "__main__":
    candidates = [2, 3, 5]
    target = 5
    c, res = [], []
    findCombination(candidates, target, 0, c, res)
    print(f"Combinations: {res}")
"""
Using c.pop()
---------------------
self.findCombination([2, 3, 5], 3, 0, [2], [])
self.findCombination([2, 3, 5], 1, 0, [2, 2], [])
self.findCombination([2, 3, 5], 0, 1, [2, 3], [])
self.findCombination([2, 3, 5], 2, 1, [3], [[2, 3]])
self.findCombination([2, 3, 5], 0, 2, [5], [[2, 3]])
Combinations: [[2, 3], [5]]

Using c = c[:-1]
---------------------
self.findCombination([2, 3, 5], 3, 0, [2], [])
self.findCombination([2, 3, 5], 1, 0, [2, 2], [])
self.findCombination([2, 3, 5], 0, 1, [2, 3], [])
self.findCombination([2, 3, 5], 2, 1, [2, 3], [[2, 3]]) # Here, mistask, 2 didn't be popped
self.findCombination([2, 3, 5], 0, 2, [2, 5], [[2, 3]])
Combinations: [[2, 3], [2, 5]]
"""

【问题讨论】:

    标签: python list recursion


    【解决方案1】:

    在 Python 中,函数参数通过引用传递,所有变量都只是对内存中实际对象的引用。

    list.pop()
    

    更改引用指向的对象。

    list=list[:-1]
    

    将引用重定向到新对象。不影响函数外的对象。

    请记住,= 总是重定向引用。

    a = [1] # reference to new object
    b = a # reference to a
    b.pop() # this changes a through b
    print(a)
    b = [1] # reference to new object, doesn't affect a anymore
    print(a)
    

    输出:

    []
    []
    

    此示例代码突出了使用函数的区别

    a = [1]
    b = [1]
    
    def f1(v):
        v.pop()
        print(v)
        # v is still a reference to a
        
    def f2(v):
        # v is a reference to b
        v = v[:-1]
        # v is now a reference to a new object
        print(v)
        
    print(a)
    f1(a)
    print(a)
    
    print(b)
    f2(b)
    print(b)
    

    输出:

    [1]
    []
    []
    [1]
    []
    [1]
    

    正确:b 不是对a 的引用,v 不是对ab 的引用。它们都是对内存中相同对象的引用。 b 不会改变 ab 改变了 a 指向的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-15
      • 2015-04-06
      相关资源
      最近更新 更多