【问题标题】:Most Pythonic way to find/check items in a list with O(1) complexity?在 O(1) 复杂度的列表中查找/检查项目的大多数 Pythonic 方法?
【发布时间】: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


【解决方案1】:

一般来说,不可能在恒定时间内找到list 中的元素。假设您可以同时维护listset,但更新操作需要线性时间。

你提到你的动机是

一个列表,而不是一个集合,主要是因为需要考虑列表中的重复项。集合不允许重复。

并要求不要专注于示例。如果这是您的动机,您可能希望使用 dict 而不是 set,将每个元素映射到其出现次数。

您可能会发现 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})

【讨论】:

  • 嗯,很高兴知道关于列表的内容。 nemanjaps 在我的问题中的评论也有助于清除有关列表和设置的一些内容。这是一个非常好的替代列表。虽然我显然不会对所有事情都使用它,但它可能正是我在不使用外部库的情况下进行大型操作所需要的。
  • 我编辑了我的问题以回应您的回答!这是一个很好的解决方案,帮助我解决了我遇到的问题,并通过列表了解未来问题的时间复杂度!非常感谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 2011-01-15
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
相关资源
最近更新 更多