在不改变第一个列表的顺序的情况下找到两个列表的公共元素的最快方法

问题描述

我有两个列表,

 l1 = [1,4,3,2,5]
 l2 = [4,10]

现在我想找到列表之间的公共元素,所以我使用以下代码

list(set(l1).intersection(set(l2)))
>> [2,4]

但是它改变了l1的顺序,我不想改变顺序所以结果应该是,

>> [4,2]

正在寻找不改变顺序的最快方法

解决方法

您可以使用 l1 对结果重新排序:

>>> sorted(set(l1).intersection(set(l2)),key=l1.index)
[4,3,2]

您也可以使用列表理解而不是集合交集,但我相信第一种方法通常会更快,具体取决于每个列表中的元素数量,因为搜索列表是 O(n) 和下面的解决方案变成O(n*m)

>>> [i for i in l1 if i in l2]
[4,2]

最后可以通过将l2转化为集合来优化理解方法:

>>> s2 = set(l2)
>>> [i for i in l1 if i in s2]
[4,2]
,

假设您想保留 l1 的序列。如果 x 存在于 l1 中,则时间复杂度为 O(n^2) 的算法将是为 x 中的每个项目 l2 找到。以下代码可以工作

common_elements = [x for x in l1 if x in l2]

您可以使用 map(dict) 将时间复杂度降低到 O(n)

lookup_map = {x: True for x in l2}
common_elements = [x for x in l1 if x in lookup_map]

编辑:发现 Python 的 set 是作为哈希映射实现的,并且在平均情况下,查找需要 O(1) https://wiki.python.org/moin/TimeComplexity,因此以下也应该有一个平均值。 O(n) 的案例复杂度

common_elements = [x for x in l1 if x in set(l2)]
,

最快的方法取决于数据,但这个解决方案应该是最快的方法之一

[x for x in [1,4,2,5] if x in {4,10}]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...