假设有两个排序列表:A和B.
A和B中的条目数可能会有所不同。 (它们可能非常小/很大。它们可能彼此相似/显着不同)。
已知什么是此功能的最快算法?
任何人都可以给我一个想法或参考吗?
答案 0 :(得分:5)
假设A
有m
个元素,B
有n
个元素,m ≥ n
。从理论上讲,我们能做的最好的事情就是
(m + n)!
lg -------- = n lg (m/n) + O(n)
m! n!
比较,因为为了验证空交集,我们基本上必须执行排序合并。我们可以通过迭代B
并在A
中保留一个“光标”来指示应该插入B
的最新元素以保持的位置,从而获得此限制的常数因子。排序顺序。我们使用exponential search来推进光标,总成本大约为
lg x_1 + lg x_2 + ... + lg x_n,
其中x_1 + x_2 + ... + x_n = m + n
是m
的某个整数分区。 O(n lg (m/n))
的凹度为lg
。
答案 1 :(得分:2)
我不知道这是否是最快的选项,但这是O(n+m)
中运行的选项,其中n
和m
是您的列表的大小:
答案 2 :(得分:0)
这是一个简单且经过测试的Python实现,它使用对分搜索来推进两个列表的指针。
假定两个输入列表都已排序并且不包含重复项。
import bisect
def compute_intersection_list(l1, l2):
# A is the smaller list
A, B = (l1, l2) if len(l1) < len(l2) else (l2, l1)
i = 0
j = 0
intersection_list = []
while i < len(A) and j < len(B):
if A[i] == B[j]:
intersection_list.append(A[i])
i += 1
j += 1
elif A[i] < B[j]:
i = bisect.bisect_left(A, B[j], lo=i+1)
else:
j = bisect.bisect_left(B, A[i], lo=j+1)
return intersection_list
# test on many random cases
import random
MM = 100 # max value
for _ in range(10000):
M1 = random.randint(0, MM) # random max value
N1 = random.randint(0, M1) # random number of values
M2 = random.randint(0, MM) # random max value
N2 = random.randint(0, M2) # random number of values
a = sorted(random.sample(range(M1), N1)) # sampling without replacement to have no duplicates
b = sorted(random.sample(range(M2), N2))
assert compute_intersection_list(a, b) == sorted(set(a).intersection(b))