在 nlog(n) 时间内对整数数组进行排序而不使用比较运算符
Posted
技术标签:
【中文标题】在 nlog(n) 时间内对整数数组进行排序而不使用比较运算符【英文标题】:Sorting an array of integers in nlog(n) time without using comparison operators 【发布时间】:2021-12-18 15:48:22 【问题描述】:想象一下有一个整数数组,但不允许您访问任何值(所以没有Arr[i] > Arr[i+1]
或其他)。区分整数的唯一方法是使用 query() 函数:该函数将元素的子集作为输入,并返回该子集中唯一整数的数量。目标是根据整数的值将整数分组——同一组中的整数应该具有相同的值,而不同组中的整数具有不同的值。
问题 - 代码必须是 O(nlog(n)),或者换句话说 query() 函数只能被调用 O(nlog(n)) 次。
我花了好几个小时在 Python 中优化不同的算法,但所有的算法都是 O(n^2)。作为参考,这是我开始使用的代码:
n = 100
querycalls = 0
secretarray = [random.randint(0, n-1) for i in range(n)]
def query(items):
global querycalls
querycalls += 1
return len(set(items))
groups = []
secretarray
生成一个长度为n
的巨大随机数字列表。 querycalls
跟踪函数被调用的次数。 groups
是结果所在。
我做的第一件事是尝试创建一个基于合并排序的算法(拆分数组,然后根据 query() 值合并),但我永远无法将它低于 O(n^2)。
【问题讨论】:
这是一个有趣的问题,但我认为标题具有误导性——“排序”意味着结果是有序的。我建议将其更改为“分区”。 【参考方案1】:假设您有一个元素 x
和一个不同元素的数组 A = [x0, x1, ..., x_k-1]
并想知道 x
是否等同于数组中的某个元素,如果是,则等同于哪个元素。
你可以做的是一个简单的递归(我们称之为check-eq
):
query([x, A]) == k + 1
。如果是,那么您知道x
与A
中的每个元素都不同。
否则,您知道x
等价于A
的某个元素。让A1 = A[:k/2], A2 = A[k/2+1:]
。如果query([x, A1]) == len(A1)
,那么你知道x
等价于A1
中的某个元素,所以在A1
中递归。否则在A2
中递归。
此递归最多需要O(logk)
个步骤。现在,让我们的初始数组为T = [x0, x1, ..., x_n-1]
。 A
将是元素组的“代表”数组。您要做的是首先获取A = [x0]
和x = x1
。现在使用check-eq
查看x1
是否与x0
在同一组中。如果没有,那么让A = [x0, x1]
。否则什么都不做。继续x = x2
。你可以看看它是怎么回事。
复杂性当然是O(nlogn)
,因为check-eq
被准确地调用了n-1
次并且每次调用都需要O(logn)
时间。
【讨论】:
以上是关于在 nlog(n) 时间内对整数数组进行排序而不使用比较运算符的主要内容,如果未能解决你的问题,请参考以下文章
leetcode:First Missing Positive分析和实现
使用 O(m) 空间在 O(n) 时间内对向量<int>(n) 进行排序?