凡是遍历L1
,通过所有的每次L2
迭代,将采取二次时间。唯一的改进方法是避免遍历所有L2
。 (有一个类似的问题在最后去除L
重复。)
如果您使用L2
(和L
)一set
,当然每个in L2
一步是恒定的时间,所以整个算法是线性的。而且您始终可以构建自己的散列表实现,而不是使用set
。但这是很多工作。
使用二叉搜索树,或者甚至只是一个排序列表和binary_find
函数,您可以在O(N log N)中执行此操作。那binary_find
写起来要容易得多。所以:
S2 = sorted(L2)
L = [element for element in L1 if binary_find(element, S2)]
S = remove_adjacent(sorted(L))
或者更简单地说,排序L1一样,那么你不需要remove_adjacent
:
S1, S2 = sorted(L1), sorted(L2)
L = []
for element in S1:
if binary_find(element, S2) and (not L or L[-1] != element):
L.append(element)
无论哪种方式,这是O(N日志N),其中N是长列表的长度。相比之下,原来的是O(N^2),其他的答案是O(N^3)。当然这有点复杂,但它仍然很容易理解。
你需要编写binary_find
(如果适用的话,remove_adjacent
),因为我假设你不想使用stdlib中的东西,如果你甚至不想使用额外的内建函数。但那真的很简单。例如:
def binary_find(element, seq):
low, high = 0, len(seq),
while low != high:
mid = (low + high) // 2
if seq[mid] == element:
return True
elif seq[mid] < element:
low = mid+1
else:
high = mid
return False
def remove_adjacent(seq):
ret = []
last = object()
for element in seq:
if element != last:
ret.append(element)
last = element
return ret
如果你甚至不希望使用sorted
或list.sort
,你可以很容易地编写自己的排序了。
你是什么意思是“以重复的照顾”吗? – Blender 2013-02-13 01:29:38
“不使用builtins”是什么意思? 'list'与'set'同样重要,'list .__ getitem__'与'set.intersection'一样是内建的,依此类推。 – abarnert 2013-02-13 01:39:52
@Blender我的意思是我想交集([1,1,2],[1,2,2])返回[1,2]而不是[1,1,2],如果我不不要删除每个列表中的元素。 – noobProgrammer 2013-02-13 01:40:01