python流量控制功能很奇怪

时间:2018-05-18 19:10:07

标签: python list for-loop interpreter

我试图用DP解决背包问题。基本上,目标是看看我们是否可以将列表中的某些元素总和达到总和的一半。

def canPartition(nums):
    """
    :type nums: List[int]
    :rtype: bool
    """
    run_sum = 0
    for num in nums:
        run_sum += num

    if run_sum & 1 == 1:
        return False
    run_sum //= 2

    n = len(nums)
    dp = [[False] * (run_sum+1)] * (n+1)

    for i in range(n+1):
        dp[i][0] = True

    for j in range(1, run_sum+1):
        dp[0][j] = False
    print("initial stage")
    print(dp)

    for i in range(1, 2):
        for j in range(1, run_sum+1):
            dp[i][j] = dp[i-1][j]
            print("inner loop after operation 1:")
            print(dp)
            if j >= nums[i-1]:
                print("inner loop after operation 2:")
                print(i, j)
                dp[i][j] |= dp[i-1][(j - nums[i-1])]
                print(dp)
                print(" ")

    return dp[n][run_sum]

nums = [1, 2, 5]
canPartition(nums)

目标本身并不重要。但是最后一个嵌套循环的流量控制表现得非常奇怪。以下是打印结果。

initial stage
[[True, False, False, False, False], [True, False, False, False, False], [True, False, False, False, False], [True, False, False, False, False]]
inner loop after operation 1:
[[True, False, False, False, False], [True, False, False, False, False], [True, False, False, False, False], [True, False, False, False, False]]
inner loop after operation 2:
1 1
[[True, True, False, False, False], [True, True, False, False, False], [True, True, False, False, False], [True, True, False, False, False]]

inner loop after operation 1:
[[True, True, False, False, False], [True, True, False, False, False], [True, True, False, False, False], [True, True, False, False, False]]
inner loop after operation 2:
1 2
[[True, True, True, False, False], [True, True, True, False, False], [True, True, True, False, False], [True, True, True, False, False]]

inner loop after operation 1:
[[True, True, True, False, False], [True, True, True, False, False], [True, True, True, False, False], [True, True, True, False, False]]
inner loop after operation 2:
1 3
[[True, True, True, True, False], [True, True, True, True, False], [True, True, True, True, False], [True, True, True, True, False]]

inner loop after operation 1:
[[True, True, True, True, False], [True, True, True, True, False], [True, True, True, True, False], [True, True, True, True, False]]
inner loop after operation 2:
1 4
[[True, True, True, True, True], [True, True, True, True, True], [True, True, True, True, True], [True, True, True, True, True]]

你可以看到,即使i的值对于整个嵌套循环都是1,不知何故在循环中修改了dp [i> 1]的值。甚至1到4的j也被修改了。就好像循环中还有另一个“for i in range()”。有谁知道为什么会这样?我用python 3.6.1

运行代码

2 个答案:

答案 0 :(得分:3)

这一行

dp = [[False] * (run_sum+1)] * (n+1)

创建n + 1False相同列表的>>> x = [[False]]*3 >>> x [[False], [False], [False]] >>> x[0][0] = True >>> x [[True], [True], [True]] 个引用列表。一个更简单的例子:

*

您几乎不想将dp = [[False for _ in range(run_sum+1)] for _ in range(n+1)] 与列表一起使用;使用列表推导代替获得独立列表:

{{1}}

答案 1 :(得分:0)

在这一行

 dp = [[False] * (run_sum+1)] * (n+1)

* (n+1)并没有神奇地创建内部列表的副本。相反,它只是列出(n+1)对同一列表的引用。