给定 O(1) 或 O(log N) 时间中的源集,有没有办法在数学上生成排序排列和数组的给定索引?
Posted
技术标签:
【中文标题】给定 O(1) 或 O(log N) 时间中的源集,有没有办法在数学上生成排序排列和数组的给定索引?【英文标题】:Is there a way to mathematically generate a given index of a sorted permutation sum array given the source set in O(1) or O(log N) time? 【发布时间】:2022-01-20 21:21:55 【问题描述】:给定一组大小为 N 且按升序排序的整数。为简单起见,这个数组“arr”如下:[a0, a1, a2, ..., aN]
。我需要所有对 ai
和 aj
之和的数组,允许重复:[a0 + a0, a0 + a1, a0 + a2, ..., a1 + a0, a1 + a1, ... aN + aN]
,大小 N^2。但是,我需要按排序顺序对其进行二进制搜索(在 O(log(N^2)) 时间内),而不必生成整个数组,这将花费 O(N^2 log(N^2)) 时间.由于二进制搜索只需要特定索引处的数组值,我想知道是否有一个数学函数来确定给定特定索引的排序排列和数组的值(例如,value(3)
将返回ak + am
),允许我在不完整生成数组的情况下对数组进行二进制搜索?我在想这样的事情:
int value(int index)
return arr[index/N] + arr[index%N];
但这并没有考虑到arr[i] + arr[k]
的值可能大于arr[i+1] + arr[k-5]
,例如,即使arr[i+1] > arr[i]
。 TLDR;对于这种特殊的数组情况,有什么方法可以在少于 O(N) 的时间内进行分区?出于我自己的目的,我还可以接受一种在不到 O(N^2) 时间内生成整个排序数组的解决方案。
【问题讨论】:
在最坏的情况下,任何一对都可能是第 k 个元素(除了 k=1,2,n^2-1 和 n^2 的一些琐碎情况),所以至少你必须遍历所有对一次以跟踪 n^2 次的 k 最小对。您的原始数组已排序的事实实际上根本没有帮助。例如,如果 a0=1 和 a1=100,那么 101 到 200 之间的任何值都可能是第三个元素,它可能以多种方式发生。您仍然需要彻底检查大量元素组合,以确保您没有错过任何一个 @apokryfos 你是说我们不能比 O(n^2) 更好地找到 n^2 和中的第 k 个最小的吗? @user2533504 你的二分搜索结果是什么?你用它做什么? 你提前知道你的二分搜索查询吗?如果您有一批查询要处理,您可以通过按排序顺序处理查询来加速整个算法。 @KellyBundy 我基本上只是想要一种方法来快速找到 n^2 数组中有多少元素小于某个数字 k,也就是排序数组中的 k 索引。 【参考方案1】:您将无法在少于O(N^2)
的时间内生成整个二维数组,因为您需要通过O(1)
将每个值附加/插入到您的数组中,并且有N^2
元素来执行此操作为了。这自动需要O(N^2)
工作。
但是,您可以在不构造完整数组的情况下进行查询。我高度怀疑您将无法击败O(n)
时间。我这么说的原因是因为我们可以在O(log n)
时间查询排序列表的唯一原因是因为我们已经投入了先前的工作来对这些元素进行排序,这需要检查每个元素并做一些工作(因此,至少@ 987654328@),我的直觉告诉我,我们在这里处于类似的情况,只是我们还没有完成必要的预计算。
现在,您可以按原样在O(n)
时间查询它。首先初始化两个指针——base
和count
,其中base
指向列表中的第一个元素,count
指向最后一个元素。还将整数 total
初始化为 0
。对于每个步骤,请执行以下操作:
count
向后移动(朝向第一个元素),直到count
的值加上base
的值的总和小于查询值(*count + *base < query
)。
将count
(索引/偏移)添加到total
向前移动base
重复直到任一指针到达其远端(包括)之后
base
指针表示一个值,我们希望知道可以添加多少其他元素并且仍然小于查询值。指针count
表示可以添加到base
并且仍然小于查询值的最后一个元素,因此为每个base
添加count
(索引)给我们元素对的总数那总和小于查询。总之,这是O(n)
,因为我们只是在初始数组上迭代,每个方向最多一次。
【讨论】:
这解决了 OP 在给定查询 value 的情况下执行二进制搜索的实际问题。您是否知道相同的两个指针方法是否可以扩展到标题中的问题,即在给定查询 index 的情况下查找值? @kcsquared 鞍背搜索确实在this algorithm 中对更普遍的问题起作用。以上是关于给定 O(1) 或 O(log N) 时间中的源集,有没有办法在数学上生成排序排列和数组的给定索引?的主要内容,如果未能解决你的问题,请参考以下文章
在 O(log(n)) 时间内从 std::set 中随机选择一个元素
f = Ω(log n) 和 g = O(n) 是 g(n) = O(f (n))
在 O(K*log(K)) 中打印给定堆中最大的 K 个元素?
c_cpp [bs] [array]搜索范围。给定排序的整数数组,找到给定目标值的起始位置和结束位置。 O(log n)