繁体   English   中英

具有lambda函数的filter()的复杂性分析

[英]Complexity analysis of filter() with a lambda function

给出两个列表, list1list2

list3 = filter(lambda x: x in list1,list2)

这将返回两个列表的交集。

如何找到此算法的复杂性? 我发现x in list1x in list1的时间复杂度是O(n) ,其中n是列表中元素的数量,但filter怎么样?

您的代码对元素执行O(len(list1) * len(list2))比较操作。

  • 你的lambda函数执行O(len(list2))次,每个元素被过滤一次。 请参阅Python 3Python 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))时间内构建一个list1set并对其运行过滤器,其中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) ,其中nlist1的大小, mlist2的大小。 然而,这种分析虽然看似合理,但取决于交集的底层python实现(可能使用排序,因此复杂性可能是O(logn+logm)或sth)

为了进行实验测试并验证结果,请使用:

  1. 生成具有不同项目和大小的各种测试列表(包括重复项)
  2. 使用测试列表测试功能并测量所用时间
  3. 绘制时间与列表大小的结果,以验证(实验)复杂性

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM