def elapsed_time(f):
start = time.time()
result = f()
finish = time.time()
return result, finish - start
def test(n, remove_max):
r = random.Random(n)
a = [r.random() for _ in range(n)]
_, t = elapsed_time(lambda: remove_max(a))
print(remove_max.__name__, '{:10d}'.format(n), '{:6.3f}'.format(t))
for p in range(1, 9):
n = 10 ** p
for rm in (remove_max_1, remove_max_2, remove_max_3, remove_max_4, remove_max_5, remove_max_6, remove_max_7, remove_max_8):
test(n, rm)
def del_max_fast(arr):
biggest = arr[0]
index_of_biggest = 0
for index, element in enumerate(arr):
if element > biggest:
biggest, index_of_biggest = element, index
del arr[index_of_biggest]
return arr
由于我们询问了最快的,我们将考虑所有建议的选项,再加上一个。
1.第一个提议的选项。最快的之一,尽管它需要两次通过列表和删除后的尾部副本:
2.最坏的选择。最大被发现
N次数。二次复杂度,最后一位:3.上一版本的优化。难度再次变为线性。速度不是最高的,作为一个副本:
4.第一首主题的变奏。而不是
pop这里del:5.最优雅的选择。两遍,一份,同第一份:
6.最大优化。一次通过,不抄袭。相反,最后一个元素被写入代替最大值,然后列表被缩短一。不是最快的,事实证明:
7.不顾一切地尝试使第一个选项更快。删除了尾部副本:
8.另一种一次性方法。这个比坦率地说不成功的六号要好,尽管删除时有一个副本:
9.你可以通过对 NlogN 的排序找到最大值。但是对于一个常数,可以在不重新排序的情况下删除最大值:
结果表:
最糟糕的#2 - 你不能欺骗一个大人物。No. 9 - 分拣开始迅速但落后,再次O-big。第 6 次,在通过次数方面是最佳的,但并不是最快的 - 在 Python 中的一次通过比在 C 中的两次通过更差。第 3 号落后,因为它创建了列表的副本。8号单传中的佼佼者。1号、4号、5号密集组-两次传球,一份副本。最后,由于拒绝抄袭,他们被7号稍微绕过。
如何进行测量
您可以使用以下方法
remove:所有给出的答案都隐含地假设列表中的最大值为一。
如果不是这种情况,他们根本无法解决问题。
这是解决方案。
请享用。是的,我们在排序的第一阶段就输了。那是 n*ln(n) 操作。但是,如果列表中有 2 个或更多最大值,则在未排序列表中搜索下一个的计算结果为 n/2。
也就是说,我们必须在此处给出的算法中的 n*ln(n) 和之前的算法 n + n/2*k 之间进行选择,其中 k 是原始列表中最大值的数量)
2.1)从没有最大元素的旧列表组装一个新列表
2.2)通过索引删除最大元素
偶然地,代码结果就像来自 nomnoms12 的另一个答案一样,但我想发送它;)