假设我有一个列表和另一个元组,它们都已经排序:
A = [10, 20, 30, 40] B = (20, 60, 81, 90)
我需要的是将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)
假设大小为A的A和大小为n的B; x
在最坏的情况下,这个解决方案需要O(m n),我怎样才能让它表现更好?
一个简单的方法是heapq.merge:
A = [10, 20, 30, 40] B = (20, 60, 81, 90) from heapq import merge for ele in merge(A,B): print(ele)
输出:
10 20 20 30 40 60 81 90
使用其他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
如果你想自己动手,这比合并要快一些:
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
一些时间:
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