我面临的问题是在O(1)复杂度的列表中查找/检查项目。以下具有O(n)的复杂性:
'foo' in list_bar
由于您在in
上使用list
关键字,因此其复杂度为O(n)。 (请参阅Python Time Complexity)
但是,如果您在in
上使用set
关键字,则其复杂度为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,伪代码或其他语言显示更好的方式来执行该操作,我很乐意阅读它。)
谢谢!
修改
为了回应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!谢谢!
答案 0 :(得分:7)
通常,在list
中不可能在恒定时间内找到元素。您可以假设维护list
和set
,但更新操作将需要线性时间。
你提到你的动机是
列表而非集合主要是由于需要考虑列表中的重复项目。集合不允许重复。
并要求不要关注这个例子。如果这是您的动机,您可能希望使用set
而不是dict
将每个元素映射到其出现次数。
您可能会发现collections.Counter
特别有用:
In [1]: from collections import Counter
In [2]: Counter(['h', 'e', 'l', 'o', 'o', 'z'])
Out[2]: Counter({'e': 1, 'h': 1, 'l': 1, 'o': 2, 'z': 1})