array[:] 在这个回溯算法中,或者更确切地说在 Python 中到底做了啥?

Posted

技术标签:

【中文标题】array[:] 在这个回溯算法中,或者更确切地说在 Python 中到底做了啥?【英文标题】:What does array[:] exactly do in this backtracking algorithm, or rather in Python?array[:] 在这个回溯算法中,或者更确切地说在 Python 中到底做了什么? 【发布时间】:2020-03-01 16:29:16 【问题描述】:

所以,我正在解决(或者更确切地说,查看解决方案哈哈)Leetcode 上的一个问题,这是一个允许您生成具有唯一整数的数组的所有可能排列的解决方案。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:

        length = len(nums)
        results = []

        def backtrack(first_char_index):
            if first_char_index == length:
                # print(nums == nums[:])
                results.append(nums)

            for index in range(first_char_index, length):
                nums[first_char_index], nums[index] = nums[index], nums[first_char_index]
                backtrack(first_char_index + 1)
                nums[first_char_index], nums[index] = nums[index], nums[first_char_index]

        backtrack(0)
        return results

所以,我正在测试解决方案,我意识到这个解决方案只有在backtrack 函数内部的if 条件内才有效,我使用results.append(nums[:]) 而不是上面的results.append(nums)

所以我最初认为这可能是因为应该使用nums[:],因为我们需要生成一个新副本,但后来我在results.append(nums)之前添加了那个打印语句,发现所有的打印语句都给了我True 结果。

我记得看到过一些使用nums[:] 而不是nums 的模式的解决方案,并且想问是否有人可以阐明额外的 [:] 究竟是做什么的?我知道它会创建一个新副本(即不同的对象,但值相同),但既然它具有相同的值,为什么会导致不同的结果?

为了说明这一点,输入[1, 2, 3] 的结果给出了

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

当使用nums,和

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

(正确答案),当使用nums[:]时。

提前致谢!

编辑:出于某种原因,这个问题被认为与其他有关深/浅复制的问题相同。但是,我想我在这里要问的是,由于[:] 会产生一个具有相同值 的新的不同对象,并且事实上numsnums[:] 的值是一样的(它打印出来是改变的值),它不应该附加一个具有改变值的数组,而不是原始未触及的nums 数组吗?

【问题讨论】:

nums == nums[:] 检查值相等,而不是对象标识。尝试nums is nums[:] 来检查副本。 这能回答你的问题吗? Python list slice as shallow copy 【参考方案1】:

nums 和 nums[:] 确实具有相同的值(您可以使用 == 检查),但它们是不同的对象(您可以使用 'is' 关键字检查)。序列是可变的,因此您可以在不更改对象本身的情况下更改它们包含的值。 [:] 只是创建现有序列的副本。这样你就有了一个不同的对象,其中包含前一个对象的所有值

编辑: 原因是,当您将 nums 附加到结果时,即使它在结果中,仍然可以更改 nums。因此,每次更改原始数字时,结果中的元素都会更改(实际上结果中的所有值都是相同的)。相反,如果您为放入结果中的每个元素创建一个副本,则这些元素都将具有不同的值。

【讨论】:

是的,我从过去的实验中认为这是正确的(即我就是这样得到它创建一个新副本的事实)。但是,它们的值是相同的,所以我的问题是为什么附加到结果的数组不一样? 因为它们是不同的对象(因此它们具有不同的内存地址)。这样,如果您更改 nums 的副本,您将不会同时更改原始副本。如果不使用 [:],通过更改 nums 的副本(例如附加值),您也将更改原始 nums。 我仍然不明白为什么将“原始值”附加到结果数组中。当然,我知道 nums[:] 允许我们不编辑原始数组,但是如果 nums 的值与 nums[:] 相同,那么附加到结果数组的数组的值不应该是 改变了一个而不是原来的一个? 原因是,当您将 nums 附加到结果时,即使它在结果内,仍然可以更改 nums。因此,每次更改原始数字时,结果中的元素都会更改(实际上结果中的所有值都是相同的)。相反,如果您为放入结果中的每个元素创建一个副本,则这些元素都将具有不同的值。 好的,这回答了我的问题!如果您要编辑并将其添加到上面的答案中,我会将其标记为正确:) 谢谢!

以上是关于array[:] 在这个回溯算法中,或者更确切地说在 Python 中到底做了啥?的主要内容,如果未能解决你的问题,请参考以下文章

java 以编程方式设置布局重力或者更确切地说在父FrameLayout底部对齐视图 - 来源:((FrameLayout.LayoutParams)view.getLayou

Javascript 是不是支持 PHP 中的短三元(更确切地说,变体)?

在事件处理函数中的 this

IDDFS(迭代加深搜索)精选题and总结

Qt 是如何工作的(确切地说)?

有人可以帮助解释这个回溯算法中的递归吗?