问题描述
python列表原地交换问题,当索引为 数组[索引]
的表达形式时,不合适的交换操作将导致错误的输出
- 法1(错误)
nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
- 法2(正确)
nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
测试
# 法1
nums1 = [3,3,2,2,1,1]
i = 0
nums1[i], nums1[nums1[i]] = nums1[nums1[i]], nums1[i]
print(nums1)
# 法2
nums2 = [3,3,2,2,1,1]
i = 0
nums2[nums2[i]], nums2[i] = nums2[i], nums2[nums2[i]]
print(nums2)
执行完成,耗时:44 ms
[2, 3, 3, 2, 1, 1]
[2, 3, 2, 3, 1, 1]
原因
执行nums1[i], nums1[nums1[i]] = nums1[nums1[i]], nums1[i]
时,python中会将左右分别形成元组,再按照先左后右的原则进行赋值,所以,不妨设
(
a
,
b
)
=
(
c
,
d
)
(a, b) = (c, d)
(a,b)=(c,d),过程为
a
=
c
,
b
=
d
a = c, b = d
a=c,b=d,所以这里将
n
u
m
s
1
[
i
]
=
n
u
m
s
1
[
n
u
m
s
1
[
i
]
]
nums1[i] = nums1[nums1[i]]
nums1[i]=nums1[nums1[i]] 时,已经更改了
n
u
m
s
[
i
]
nums[i]
nums[i] 的值,再进行
n
u
m
s
1
[
n
u
m
s
1
[
i
]
]
=
n
u
m
s
1
[
i
]
nums1[nums1[i]] = nums1[i]
nums1[nums1[i]]=nums1[i] 时,等式左边索引发生改变,故发生错误。
具体来说,
i
=
0
i = 0
i=0,先执行
n
u
m
s
1
[
0
]
=
n
u
m
s
1
[
n
u
m
s
1
[
0
]
]
nums1[0] = nums1[nums1[0]]
nums1[0]=nums1[nums1[0]],于是
n
u
m
s
1
[
n
u
m
s
1
[
0
]
]
=
n
u
m
s
1
[
3
]
=
2
nums1[nums1[0]] = nums1[3] = 2
nums1[nums1[0]]=nums1[3]=2
n
u
m
s
1
[
0
]
=
2
nums1[0] = 2
nums1[0]=2
再执行
n
u
m
s
1
[
n
u
m
s
1
[
0
]
]
=
n
u
m
s
1
[
0
]
nums1[nums1[0]] = nums1[0]
nums1[nums1[0]]=nums1[0] 时,等式右边先计算,再将值复制给左边,有:
n
u
m
s
1
[
0
]
=
2
nums1[0] = 2
nums1[0]=2
n
u
m
s
1
[
n
u
m
s
1
[
0
]
]
=
n
u
m
s
1
[
2
]
=
2
nums1[nums1[0]] = nums1[2] = 2
nums1[nums1[0]]=nums1[2]=2
于是,第二步修改了nums1[2]
的值,并没有修改nums1[3]
的值,结果为 [2, 3, 3, 2, 1, 1]
思考
对于正确的方式,在此不再详细分析