检索Python集的下一个最小元素

时间:2012-09-16 15:59:56

标签: python algorithm data-structures

Sieve of Eratosthenes是一种相当快速的生成素数的方法,最高可达k,如下所示:

  1. 从集p = (2, 3, 4, ..., k)i = 2开始。
  2. i^2开始,从i移除p的所有倍数。
  3. 重复i中的下一个最小p,直到i >= sqrt(k)
  4. 我目前的实现看起来像这样(明显优化了预过滤所有偶数):

    # Compute all prime numbers less than k using the Sieve of Eratosthenes
    def sieve(k):
        s = set(range(3, k, 2))
        s.add(2)
    
        for i in range(3, int(sqrt(k)), 2):
            if i in s:
                for j in range(i ** 2, k, i * 2):
                    s.discard(j)
    
        return sorted(s)
    

    编辑:以下是基于list的等效代码:

    def sieve_list(k):
        s = [True] * k
        s[0] = s[1] = False
        for i in range(4, k, 2):
            s[i] = False
    
        for i in range(3, int(sqrt(k)) + 2, 2):
            if s[i]:            
                for j in range(i ** 2, k, i * 2):
                    s[j] = False
    
        return [2] + [ i for i in range(3, k, 2) if s[i] ]
    

    这有效,但并不完全正确。这些行:

    for i in range(3, int(sqrt(k)), 2):
        if i in s:
            [...]
    

    通过测试每个奇数的集合成员资格来查找s的下一个最小元素。理想情况下,实现应该是:

    while i < sqrt(k):
        [...]
        i = next smallest element in s
    

    然而,由于set是无序的,我不知道如何(或者甚至可能)以更有效的方式获得下一个最小元素。我考虑使用带有list / True标记的False作为素数,但您仍需要走list寻找下一个True元素。您不仅可以实际删除list中的元素,因为这样就无法在步骤2中有效地删除复合数字。

    有没有办法更有效地找到下一个最小元素?如果没有,是否有其他数据结构允许按值删除O(1)并找到下一个最小元素的有效方法?

2 个答案:

答案 0 :(得分:6)

集合是无序的,因为它们在内部实现为散列集。没有有效的方法可以在这样的数据结构中找到最小元素; min(s)将是最恐怖的方式(但它是O(n))。

你可以使用collections.deque 你的套装。使用deque按排序顺序存储元素列表。每当你需要从deque中获得最小的弹出元素,直到你找到一个在你的集合中。这在整个输入数组中分摊了O(1)成本(因为你只需要弹出n次)。

我还应该指出,可以有 no 数据结构从列表中创建O(n)(或O(1)插入),按值删除O(1)和O (1)最低限度;这样的数据结构可以用于简单地实现O(n)一般排序,这是(信息理论上)不可能的。 hashset非常接近,但必须牺牲有效的最小值。

答案 1 :(得分:0)

您可以使用列表代替集合。对于未标记的,使用None初始化列表。您可以使用元素索引作为数字。

  1. 初始化列表
  2. 从p = 2开始
  3. 将列表中p的所有倍数标记为标记为
  4. 的“M”
  5. 在列表中找到下一个未标记的元素,并将其设为新的p。如果没有,你就完成了。
  6. 如果您需要查找下一个未标记的索引,您只需查看索引p之后的元素并且等于None。