[英]Complexity analysis of filter() with a lambda function
给出两个列表, list1
和list2
list3 = filter(lambda x: x in list1,list2)
这将返回两个列表的交集。
如何找到此算法的复杂性? 我发现x in list1
中x in list1
的时间复杂度是O(n) ,其中n是列表中元素的数量,但filter
怎么样?
您的代码对元素执行O(len(list1) * len(list2))
比较操作。
你的lambda函数执行O(len(list2))
次,每个元素被过滤一次。 请参阅Python 3 ( Python 2 )中有关filter
文档 :
filter(function, iterable)
从
iterable
那些元素构造一个iterator
,函数返回true 。iterable
可以是序列,支持迭代的容器,也可以是迭代器
(强调我的)
显然,对于iterable中的每个(不同)元素,函数被调用至少1次 - 知道何时不需要调用它也意味着在一般情况下也解决Halting问题,即使Python核心开发人员还没有解决;-) 。 在CPython 3的实践中, 内置filter
创建一个迭代器,当它前进时 ,在迭代顺序中为每个元素(不同或不同)执行一次函数。
如记录所示x in list1
中的x in list1
平均和最差情况下进行O(len(list1))
比较。
为了加快速度,请使用set
; 你根本不需要lambda函数(使用__contains__
magic方法)
list3 = filter(set(list1).__contains__, list2)
这将在O(len(list1))
时间内构建一个list1
的set
并对其运行过滤器,其中O(len(list2))
平均复杂度为O(len(list1) + len(list2))
如果list2
元素的顺序无关紧要,那么你也可以这样做
set(list1).intersection(list2)
它应该比上面的filter
具有更低的常数; 对于真正快速的代码,你应该对列表进行排序,以便将较小的代码转换成一个集合(因为交集和集合构建都记录了O(n)
平均复杂度,但是由于调整大小,set set很可能会有更大的常量set
,因此从较小的构建集合以减少这些常量的权重是有意义的):
smaller, larger = sorted([list1, list2], key=len)
result = set(smaller).intersection(larger)
请注意,Python 2和3彼此不同。 Python 3中的filter
返回一个生成器,实际运行时间取决于生成的生成器消耗的元素数量,而在Python 2中,将预先生成一个列表,如果只需要第一个值,则可能成本更高。
复杂度可以是O(nm)
,其中n
是list1
的大小, m
是list2
的大小。 然而,这种分析虽然看似合理,但取决于交集的底层python实现(可能使用排序,因此复杂性可能是O(logn+logm)
或sth)
为了进行实验测试并验证结果,请使用:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.