'in' 表示复杂度最低的两个排序列表

Tom*_*eus 8 python

我有两个排序列表,例如

a = [1, 4, 7, 8]
b = [1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

我想知道每个项目a是否在b. 对于上面的例子,我想找到

a_in_b = [True, True, False, False]
Run Code Online (Sandbox Code Playgroud)

(或具有索引其中a_in_bTrue将细太)。

现在,ab都非常大,因此复杂性是一个问题。如果M = len(a)N = len(b)我怎样才能以比M * O(N)利用两个列表都已排序的事实更低的复杂性来做到这一点?

Blc*_*ght 6

您可以在循环b中手动迭代您的列表a。当您从中b看到的最新值小于 中的当前值时,您将需要推进迭代a

from math import inf

result = []
b_iter = iter(b)                           # create an iterator over b
b_val = -inf
for a_val in a:
    while b_val < a_val:
        b_val = next(b_iter, inf)          # manually iterate on it
    result.append(a_val == b_val)
Run Code Online (Sandbox Code Playgroud)

这应该有一个运行时间O(M+N),因为每个列表项最多迭代一次(b甚至可能不需要完全迭代)。

如果您愿意,您可以避免使用浮点无穷大,但是您需要做一些额外的工作来处理一些边缘情况(例如,如果b为空)。


Mis*_*agi 6

利用 sorted'ness 是时间复杂度的一个红鲱鱼:理想的情况是在 O(n+m) 复杂度的锁步中迭代两者。这与转换b为 O(m) 的集合,然后在a集合中搜索 O(n)的元素相同。

>>> a = [1, 4, 7, 8]
>>> b = [1, 2, 3, 4, 5, 6]
>>> bs = set(b)                 # create set for O(len(b))
>>> [item in bs for item in a]  # check O(len(a)) items "in set of b" for O(1) each
[True, True, False, False]
Run Code Online (Sandbox Code Playgroud)

由于大多数这些操作是内置的,唯一昂贵的操作是a所有解决方案都需要的迭代。

但是,这将复制对 中项目的引用b。如果b被视为算法的外部,则空间复杂度为 O(m+n) 而不是仅针对答案的理想情况 O(n)。

  • 这不是转移注意力,而是转移注意力。利用排序性的解决方案具有相同的时间复杂度,但与基于集合的解决方案的 O(m) 辅助空间相比,使用 O(1) 辅助空间。 (2认同)

小智 2

在这里使用二分搜索:

def bs(b,aele,start,end):
    if start > end:
        return False
    mid = (start + end) // 2
    if ale == b[mid]:
        return True

    if ale < b[mid]:
        return bs(b, aele, start, mid-1)
    else:
        return bs(b, aele, mid+1, end)
Run Code Online (Sandbox Code Playgroud)

对于 a 中的每个元素,使用此方法检查它是否存在于b中。时间复杂度:O(m*log(n))