【问题标题】:Finding closest number in a range查找范围内最接近的数字
【发布时间】:2013-01-07 15:56:18
【问题描述】:

我想到了一个问题,如下:

我们有一个大小为 n 的整数数组 A,我们有测试用例 t,在每个测试用例中,我们都有一个数字 m 和一个范围 [s,e],即我们有 s 和 e,我们必须在该数组(A[s]-A[e])的范围内找到最接近的 m 数。

你可以假设数组索引是从 1 到 n。

例如:

  A = {5, 12, 9, 18, 19}
  m = 13
  s = 4 and e = 5

所以答案应该是 18。

约束:

n<=10^5
t<=n

我能想到的只是每个测试用例的 O(n) 解决方案,我认为存在更好的解决方案。

【问题讨论】:

  • 如果它没有以任何方式排序,那么你必须访问 A[s] 和 A[e] 之间的每个值,所以它是 O(n)。或者更确切地说是 O(e-s),我想。
  • @femtoRgon 我知道,但是通过使用任何数据结构我认为这是可能的(只是想但不确定)。
  • 既然您指定了最大尺寸界限 (10^5),那么复杂度不是 O(1) - 即恒定时间吗?
  • @Chris 这是对不超过其值的元素数量的限制
  • @izomorphius 如果数字应该是无限精度整数,那么到目前为止给出的复杂度数字是错误的。

标签: algorithm complexity-theory


【解决方案1】:

这是一个粗略的草图: 从数据创建一个segment tree。在每个节点上,除了左右索引等常规数据外,您还存储在以该节点为根的子树中找到的数字,按排序顺序存储。当您以自下而上的顺序构建分段树时,您可以实现这一点。在叶子正上方的节点中,您按排序顺序存储两个叶子值。在中间节点中,您将数字保留在左孩子和右孩子中,您可以使用标准合并将它们合并在一起。树中有 O(n) 个节点,保存这些数据总共需要 O(nlog(n))。

一旦你有了这棵树,对于每个查询,沿着路径走,直到你到达给定范围([s,e])中的适当节点。如教程所示,一个或多个不同的节点将组合形成给定的范围。由于树深度为 O(log(n)),即每次查询到达这些节点的时间。每个查询应该是 O(log(n))。对于完全位于范围内的所有节点,使用二进制搜索在存储在这些节点中的排序数组中找到最接近的数字。同样,O(log(n))。在所有这些中找到最接近的,这就是答案。因此,您可以在 O(log(n)) 时间内回答每个查询。

我链接到的教程包含其他数据结构,例如稀疏表,它们更容易实现,并且每个查询应该给出 O(sqrt(n))。但我并没有想太多。

【讨论】:

  • 如何决定将哪些节点放入树中?您不能添加所有可能的左右索引。
  • 在数组的顶部构建一个段树(每个数组元素是一个叶子),每两个叶子节点组合起来给出一个下一级节点,依此类推。您可以按照教程中的说明在数组上构建整个树。然后,在任何给定范围内搜索聚合数据需要遍历树中最多两个分支。
  • 好的,现在知道了。我很糟糕 - 我曾使用线段树,但不知何故无法想象它们如何解决这个问题。
  • @mayank 我认为您的陈述“最多可能有 2 个不同的节点可以组合形成给定的范围”可能不正确,因为可以通过使用两个以上的节点来形成范围,例如说当总范围为 [1,8] 并且所需范围为 [2,7] 时,使用了分段树的四个节点。如果我错了,请纠正我。
  • @AkashdeepSaluja 是的,再想想,你是对的。目标节点的数量可能超过 2。但遍历时间仍然是 O(log(n)),尽管我无法严格证明。我将编辑我的答案。
【解决方案2】:

对数组进行排序并进行二分查找。复杂度:o(nlogn + logn *t)

【讨论】:

  • 将不起作用 - 您将原始数组中的索引作为查询的一部分。再次阅读声明。
【解决方案3】:

我很确定不存在更快的解决方案。您的问题的一个细微变化是:

没有数组 A,但是每个测试用例都包含一个未排序的数字数组来搜索。 (A从s到e的数组切片)。

在这种情况下,显然没有比对每个测试用例进行线性搜索更好的方法了。

现在,您的原始问题在什么方面比上述变体更具体?唯一添加的信息是所有切片都来自同一个数组。我认为这个额外的约束不能用于算法加速。

编辑:我的立场是正确的。段树数据结构应该可以工作。

【讨论】:

  • 这不是一个微小的变化,而是一个主要的区别。如果您提前拥有A,您可能能够在预处理期间创建一个数据结构,以实现更快的搜索。
  • 我的论点是不存在这样的数据结构,但不同答案中的段树想法让我相信。
猜你喜欢
  • 2019-12-15
  • 2016-03-05
  • 2023-02-17
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 2017-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多