ana*_*and 5 python algorithm optimization
假设我有一个列表和另一个元组,它们都已经排序:
A = [10, 20, 30, 40]
B = (20, 60, 81, 90)
Run Code Online (Sandbox Code Playgroud)
我需要的是将A中的所有元素添加到A中,使A保持排序.
我可以带来的解决方案是:
for item in B:
for i in range(0, len(A)):
if item > A[i]:
i += 1
else:
A.insert(i, item)
Run Code Online (Sandbox Code Playgroud)
假设大小为A的A和大小为n的B; x在最坏的情况下,这个解决方案需要O(m n),我怎样才能让它表现更好?
Pad*_*ham 11
一个简单的方法是heapq.merge:
A = [10, 20, 30, 40]
B = (20, 60, 81, 90)
from heapq import merge
for ele in merge(A,B):
print(ele)
Run Code Online (Sandbox Code Playgroud)
输出:
10
20
20
30
40
60
81
90
Run Code Online (Sandbox Code Playgroud)
使用其他O(n)解决方案的一些时间:
In [53]: A = list(range(10000))
In [54]: B = list(range(1,20000,10))
In [55]: timeit list(merge(A,B))
100 loops, best of 3: 2.52 ms per loop
In [56]: %%timeit
C = []
i = j = 0
while i < len(A) and j < len(B):
if A[i] < B[j]:
C.append(A[i])
i += 1
else:
C.append(B[j])
j += 1
C += A[i:] + B[j:]
....:
100 loops, best of 3: 4.29 ms per loop
In [58]: m =list(merge(A,B))
In [59]: m == C
Out[59]: True
Run Code Online (Sandbox Code Playgroud)
如果你想自己动手,这比合并要快一些:
def merger_try(a, b):
if not a or not b:
yield chain(a, b)
iter_a, iter_b = iter(a), iter(b)
prev_a, prev_b = next(iter_a), next(iter_b)
while True:
if prev_a >= prev_b:
yield prev_b
try:
prev_b = next(iter_b)
except StopIteration:
yield prev_a
break
else:
yield prev_a
try:
prev_a = next(iter_a)
except StopIteration:
yield prev_b
break
for ele in chain(iter_b, iter_a):
yield ele
Run Code Online (Sandbox Code Playgroud)
一些时间:
In [128]: timeit list(merge(A,B))
1 loops, best of 3: 771 ms per loop
In [129]: timeit list(merger_try(A,B))
1 loops, best of 3: 581 ms per loop
In [130]: list(merger_try(A,B)) == list(merge(A,B))
Out[130]: True
In [131]: %%timeit
C = []
i = j = 0
while i < len(A) and j < len(B):
if A[i] < B[j]:
C.append(A[i])
i += 1
else:
C.append(B[j])
j += 1
C += A[i:] + B[j:]
.....:
1 loops, best of 3: 919 ms per loop
Run Code Online (Sandbox Code Playgroud)