所以我正在做一个问题,计算对数字 1、2、3、...、n 进行排序所需的最小交换次数。
现在我能够解决这个问题,但我必须用语法做一个非常具体的事情才能让它工作。有没有人介意帮助我理解为什么我必须这样做。
我的原始代码是:
def minimumSwaps(arr):
c = 0
for index in range(len(arr)):
value = arr[index]
if not index + 1 == value:
#new_i = arr.index(index+1)
print(str(index) + " -> " + str(new_i))
arr[index], arr[arr.index(index+1)] = arr[arr.index(index+1)], arr[index]
print(arr)
c += 1
print(arr)
return c
这段代码输出的问题是:
例子:
输入:[4, 3, 1, 2]
输出:
0 -> 2
[4, 3, 1, 2]
1 -> 3
[4, 3, 1, 2]
2 -> 1
[4, 1, 3, 2]
3 -> 0
[2, 1, 3, 4]
[2, 1, 3, 4]
现在,当我将代码更改为:
def minimumSwaps(arr):
c = 0
for index in range(len(arr)):
value = arr[index]
if not index + 1 == value:
new_i = arr.index(index+1)
print(str(index) + " -> " + str(new_i))
arr[index], arr[new_i] = arr[new_i], arr[index]
print(arr)
c += 1
print(arr)
return c
我所做的只是将“arr.index(index+1)”存储在一个 var 中,并在我的交换代码中使用该变量而不是表达式,它完美地工作。
例子:
输入:[4, 3, 1, 2]
输出:
0 -> 2
[1, 3, 4, 2]
1 -> 3
[1, 2, 4, 3]
2 -> 3
[1, 2, 3, 4]
[1, 2, 3, 4]
我被这个难住了,请帮忙。
编辑 1:它实际上运行不完美,当然,我认为只在较大的输入上出现运行时错误。
这里的问题是操作顺序:
arr[index], arr[arr.index(index+1)] = arr[arr.index(index+1)], arr[index]
右边的顺序没问题=
;所有这些都在修改任何内容之前发生,因此您最终会得到一个tuple
预期值。
的问题是,在左侧的侧=
被从左到右,评价懒惰地使(各目标仅在时刻评价为项被分配)arr.index(index+1)
调用发生后分配给arr[index]
。操作顺序是(问题的症结见加粗斜体部分):
tuple
构造(做了很多事情,但都没有危险)arr
加载index
加载tuple
from #1的第一个元素分配给arr[index]
。arr
现在有不同的价值!arr
再次加载arr.index(index+1)
呼吁将arr
已经发生突变的第4步!tuple
from #1的第二个元素分配给arr[post_mutation_index]
因此,当赋值给arr[index]
意味着arr.index(index+1)
返回不同的索引时,您的代码就会出现异常。预先缓存它可以修复它,因为它会查看预突变arr
并始终如一地使用它。
为了使事情更清楚,您的代码等效于:
tmp = arr[index], arr[arr.index(index+1)]
arr[index] = tmp[0]
arr[arr.index(index+1)] = tmp[1]
(只是没有命名tmp
)。通过这种排序,更清楚的是arr.index(index+1)
调用发生在arr
已经发生变异之后,允许它arr[index]
在搜索分配另一个值时使用的索引之前找到(或找不到)一个值,因为它被分配了一个新值。
您还可以通过确保左侧.index
调用发生在任何其他突变之前来使代码工作,例如:
arr[arr.index(index+1)], arr[index]
但这将是脆弱的代码(如果维护者更改顺序,或向行中添加其他项目,则更难使其正确),并且无论如何预先缓存一次效率较低(您必须执行两次线性扫描arr
每次交换,而不仅仅是一次)。
这是有效的,因为现在的顺序是:
tuple
构造(做了很多事情,但都没有危险)arr
加载arr.index(index+1)
调用unmodified arr
,并且在发生任何索引分配后不再调用(好!)tuple
from #1的第一个元素分配给arr[pre_mutation_index]
arr
再次加载index
加载tuple
from #1的第二个元素分配给arr[index]
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句