重复大量输入的快速选择算法?

Posted

技术标签:

【中文标题】重复大量输入的快速选择算法?【英文标题】:Fast selection algorithm for duplicate-heavy inputs? 【发布时间】:2021-10-01 17:03:42 【问题描述】:

我已经熟悉了快速选择和中位数的中位数,用于快速选择未排序数组中的第 k 个元素。如果你足够努力,你可以保证最坏情况的时间复杂度在 O(n)。

我的问题有点不同。我想从包含大量不可预测重复的未排序数组中选择第 k 个数字。我想知道的是,与输入n 的总大小相比,是否存在一种既能节省内存又能节省时间的方法来处理唯一值u 的数量。问题是有时u << n 有时u ~ n。 (实际上,u 几乎是不变的,而n 波动很大。)

不好的方法1(请原谅我的python伪代码,问题与python没有具体关系):

input = ...
k = ...

m = hashmap()
for value in input:
    if value exists in m:
        m[value] = m[value] + 1
    else:
        m[value] = 1

cumulative_sum = 0
for unique_value in ordered(m):
    cumulative_sum += m[unique_value]
    if cumulative_sum > k:
        return unique_value

这是我目前的基准。我不喜欢的是使用比较对m 进行排序或保持排序需要O(u*logu) 时间。

错误方法 2:

input = ...
k = ...

M = some_value
assert type(input) == integral
assert min(input) == 0
assert max(input) == M

a = array(size=M+1, default_value=0)

for value in input:
    m[value] = m[value] + 1

cumulative_sum = 0
for i in range(M+1):
    cumulative_sum += m[i]
    if cumulative_sum > k:
        return i

这显然很糟糕,因为它需要O(M) 时间和O(M) 空间。

有没有什么好的方法来更新快速选择(或完全做其他事情)来解决O(u)时间和O(u)空间中的问题?

正如@kcsquared 所说,如果输入数组按原样给出,则无法打破Omega(n) 时间限制。如果输入格式为[(v1, c1), (v2, c2), ..., (vn, cn)],是否会发生任何变化,其中(v, c) 对应一个唯一值; v 是值,c 是它在原始输入中出现的次数?

【问题讨论】:

您是否对同一个数组进行重复的选择查询?否则,您需要至少查看数组的每个元素一次(如果您事先不知道u)所以Omega(n) 对于时间复杂度来说是不可避免的。 @kcsquared 不,只有一个选择查询。你当然是对的。假设您实际上确实提前知道 u:如果您的新输入是 2 元组 (v, c),其中 v 将是您的值,c 将是它在原始输入中出现的数量。这会改变什么吗? 荷兰国旗分区算法在这里可能有些用处。 en.wikipedia.org/wiki/Dutch_national_flag_problem @CiaPan 谢谢你的建议;可能是我遗漏了一些东西,但我认为该算法不能用于解决这个问题,因为该算法通过整个数组(jk 相遇),这使得它@ 987654349@,更不用说输入查询是一个值,而不是一个索引。 是的,基本上。这与@btilly 的第一个解决方案相同。您实际上可以随时计算子分区总和。 【参考方案1】:

为了记忆,是的。

创建一个哈希映射值来计数。此哈希的大小为O(u)。然后您可以进行快速选择,为每个值赋予与计数相等的权重。

但是,您必须阅读整个数组,即O(n)。除非您对大概的答案感到满意。在这种情况下,您可以从数组中随机选择,找出近似计数的哈希值,然后快速选择它。根据目的,这可能已经足够接近了。

【讨论】:

不幸的是,近似值是不够的(关键管道的一部分)。但是,谢谢您的回答,我想我刚刚知道更新后的快速选择是如何工作的。我明天会实施并尽快回复您!

以上是关于重复大量输入的快速选择算法?的主要内容,如果未能解决你的问题,请参考以下文章

快速排序算法

常见排序算法详解(冒泡选择插入快速希尔归并)

排序算法(冒泡排序选择排序插入排序快速排序归并排序)

排序算法(冒泡排序选择排序插入排序快速排序归并排序)

算法学习——递归之快速排序

排序算法(冒泡排序选择排序插入排序快速排序归并排序)