gpt4 book ai didi

python - 在 python 列表中交换元素的时间复杂度

转载 作者:太空狗 更新时间:2023-10-30 01:28:31 26 4
gpt4 key购买 nike

如果我执行以下操作,在 python 列表中交换元素的时间复杂度是多少

案例 1:(惯用方式)交换列表中的两个元素

>>> a = [1, 2, 3, 4, 5]
>>> a[1], a[3] = a[3], a[1] # Pythonic Swap --> x, y = y, x

>>> print(a)
[1, 4, 3, 2, 5]

问题1:交换步骤的时间复杂度是多少? python 内部是做什么的。


案例 2:(非常低效的方式)交换列表中的两个元素

>>> a = [1, 2, 3, 4, 5]
>>> temp1, temp2 = a[1], a[3]
>>> del a[1] # a = [1, 3, 4, 5]
>>> a.insert(1, temp2) # a = [1, 4, 3, 4, 5]
>>> del a[3] # a = [1, 4, 3, 5]
>>> a.insert(3, temp1) # a = [1, 4, 3, 2, 5]
>>> print(a)
[1, 4, 3, 2, 5]

如果我这样做,每当我在任何索引处插入或删除时,该索引右侧的所有内存地址都需要分别向右或向左移动/复制一步。所以它需要 O(K),其中 K 是我们插入或删除的索引右侧的地址数。如果我错了,请纠正我。


一些分析

如果列表非常小,那么运行时复杂度与我使用的任何方法(Case1 或 Case2)无关紧要。但是,如果列表非常大,如 a = [i for i in range(0,1000000)] 那么交换列表中两个元素的有效方法是什么?在这里,我使用百万记录列表交换索引 100 和 54321 对上述两种情况进行了一些基本分析,结果如下。令人惊讶的是,这两种情况的性能几乎相同。

a = [i for i in range(0,1000000)]

Case1 分析

$时间python3 case1_script.py

real    0m0.129s
user 0m0.088s
sys 0m0.041s

$ python3 -m cProfile case1_script.py

3 function calls in 0.060 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.047 0.047 0.060 0.060 list_ele_swap_profile.py:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.013 0.013 0.013 0.013 {range}

Case2 分析

$时间python3 case2_script.py

real    0m0.132s
user 0m0.090s
sys 0m0.042s

$ python3 -m cProfile case2_script.py

5 function calls in 0.115 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.048 0.048 0.115 0.115 list_ele_swap_profile.py:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
2 0.001 0.001 0.001 0.001 {method 'insert' of 'list' objects}
1 0.066 0.066 0.066 0.066 {range}

问题 2:如果列表非常大,如上所示,交换列表中两个元素的有效方法是什么。

问题 3: 在思考这个问题时我还有一个疑问,那么如果从列表需要复制/移动内存地址,那么如何从列表中删除一个元素是 O(1)。


PS:我不认为这是一个重复的问题,我已经完成了以下问题,但没有一个是我要找的。我有兴趣了解上述操作的时间/空间复杂度。谢谢。

最佳答案

答案取决于您对 python 的实现。我假设您对默认的 CPython 实现感兴趣。从现在开始,我说“python”而不是“cpython”。

Python 中的列表或多或少像 C 中的数组一样适合您的目的。

删除其中的一个元素需要移动它上面的所有元素,插入也是如此,因此这两个操作是 O(i),其中 i 是您删除/插入的项目之后的项目数。您的第一个答案是 O(1),这样更好。

你的分析是错误的,因为这个数组的大小实际上很小,而且你的时间安排也考虑了构建数组的时间。尝试以下实验:构建一次大小为 100000 的数组,并尝试交换其中的两个元素 100000 次。您会看到第一个代码比第二个代码至少快 100 倍(这是我在计算机上获得的数字),这当然是交换 python 列表中元素的好方法。

关于python - 在 python 列表中交换元素的时间复杂度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30745678/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com