【发布时间】:2017-02-25 03:18:51
【问题描述】:
我面临的问题是在 O(1) 复杂度的列表中查找/检查项目。以下复杂度为 O(n):
'foo' in list_bar
这具有 O(n) 的复杂性,因为您在 list 上使用了 in 关键字。 (参考Python Time Complexity)
但是,如果您在 set 上使用 in 关键字,则复杂度为 O(1)。
我需要计算列表而不是集合的 O(1) 复杂度的原因主要是因为需要考虑列表中的重复项。集合不允许重复。一个不错的例子是:
chars_available = ['h', 'e', 'l', 'o', 'o', 'z']
chars_needed = ['h', 'e', 'l', 'l', 'o']
def foo(chars_available, chars_needed):
cpy_needed = list(chars_needed)
for char in cpy_needed:
if char in chars_available:
chars_available.remove(char)
chars_needed.remove(char)
if not chars_needed: return True # if chars_needed == []
return False
foo(chars_available, chars_needed)
这个例子不是这里的重点,所以请尽量不要被它转移。重点仍然是尝试获得 O(1) 复杂度以在列表中查找项目。我将如何通过 Python 实现这一点?
(作为额外的荣誉,如果您确实想展示用 Python、伪代码或其他语言执行该操作的更好方法,我很乐意阅读它)。
谢谢!
编辑:
针对 Ami Tavory 的回答,我了解到您无法比 O(n) 更快地制作列表,但 collections.Counter() 的建议有助于解决我正在处理的应用程序。我正在为 Stack Overflow 上传更快的解决方案,性能非常出色!如果我没记错的话(如果我错了,请纠正我),它应该是 O(1),因为它只涉及可散列值并且没有循环迭代。
from collections import Counter
chars_available = ['h', 'e', 'l', 'o', 'o', 'z']
chars_needed = ['h', 'e', 'l', 'l', 'o']
def foo(chars_available, chars_needed):
counter_available = Counter(chars_available)
counter_needed = Counter(chars_needed)
out = counter_needed - counter_available
if not list(out.elements()): return True
else: return False
foo(chars_available, chars_needed)
非常快,非常pythonic!谢谢!
【问题讨论】:
-
您可以同时保留列表和集合,有一些数据结构可能适合您,但它们可能会做出一些权衡,例如丢失原始列表的顺序。
-
为了在列表中查找项目,您必须使用搜索算法。 Set 基本上是作为哈希映射实现的,因此它们允许您拥有 O(1)。
-
这纯粹是出于理论上的兴趣,还是有实际应用需要这个?
-
@Chris_Rands 主要是理论上的兴趣;但是在性能方面存在一些应用程序需求,因为处理器确实会陷入更大的列表中。这在竞争性编码/黑客攻击中尤其普遍。
标签: python algorithm performance python-3.x time-complexity