查找包含来自总体 A 的最大元素和来自总体 B 的零元素的标量区间

问题描述

给定两个大集合 A 和 B 的标量(浮点)值,您将使用什么算法来查找包含来自 B 的零元素和来自 A 的最大元素数的(标量)范围 [x0,x1]?

排序复杂度 (O(n log n)) 是否不可避免?

解决方法

创建一个包含所有值的列表,其中每个值都标有两个计数:一个计数与集合 A 相关,另一个与集合 B 相关。最初这些计数为 1 和 0,当值来自集合时A,当值来自集合 B 时为 0 和 1。因此此列表中的条目可以是元组(值、计数A、计数B)。这个操作是 O(n)。

对这些元组进行排序。 O(nlogn)

将有重复值的元组合并为一个元组,并在对应的计数器中累加值,让元组告诉我们该值在集合A中出现了多少次,在集合B中出现了多少次。O(n)>

按排序顺序遍历此列表,并维护一系列相邻元组的 countA 的最大计数总和,其中 countB 始终为 0,以及该范围的最小值和最大值。 O(n)

排序是时间复杂度的决定因素:O(nlogn)。

,

在 O(|A| log |A| + |B| log |B|) 中对 A 和 B 进行排序。然后应用以下算法,其复杂度为 O(|A| + |B|):

i = j = k = 0
best_interval = (0,1)

while i < len(B) - 1:
    lo = B[i]
    hi = B[i+1]
    
    j = k    # We can skip ahead from last iteration.
    while j < len(A) and A[j] <= lo:
        j += 1

    k = j   # We can skip ahead from the above loop.
    while k < len(A) and A[k] < hi:
        k += 1

    if k - j > best_interval[1] - best_interval[0]:
        best_interval = (j,k)
    
    i += 1

x0 = A[best_interval[0]]
x1 = A[best_interval[1]-1]

第一次检查时它可能看起来是二次的,但请注意我们从未减少 jk - 它实际上只是一个带有三个指针的线性扫描。