最接近的数字

时间:2015-03-14 13:12:15

标签: algorithm tree segment-tree

假设您有a1..an个号码和一些查询[l, k] (1 < l, k < n)。问题是在[l, k]区间内找到两个相等数字之间的最小距离。

示例:(间隔l,k显示为| ... |)

1 2 2 |1 0 1| 2 3 0 1 2 3

答案2(101)

1 |2 2| 1 0 1 2 3 0 1 2 3

答案1(22)

1 2 2 1 0 |1 2 3 0 3 2 3|

答案2(303)或(323)

我已经考虑了分段树,但是当在多个节点之间共享查询时,很难从每个树节点加入结果。我已经尝试了一些方法来加入它们,但它看起来很难看。有人可以给我一个暗示吗?


澄清

感谢您的回答。 问题是有很多查询,所以o(n)不好。我不小心提到了一个分段树。它会执行[l, r]查询,以便在[l, r]SUM复杂度的数组中查找[l, r]MINlog(n)。我们可以在这里进行一些预处理以适应o(logn)吗?

2 个答案:

答案 0 :(得分:1)

如果第一个数字等于最后一个数字,则调用间隔 minimal 但是间隔中的每个数字只出现一次。 11和101是最小的,但12021和10101不是。

在线性时间内(假设恒定时间散列),枚举所有最小间隔。这可以通过保留两个索引lk以及将lk之间的每个符号映射到其索引的哈希映射来完成。最初是l = 1k = 0。反复执行以下操作。增量k(如果它太大,我们就会停止)。如果k的新值处的符号位于地图中,则将l提升到地图值,然后在我们前往地图中删除内容。产生间隔[l, k]并再次增加l。在所有情况下,请将k写为符号的映射值。

由于极小,最小间隔按其左右端点以相同的方式排序。为了回答查询,我们查找它可以包含的第一个区间和最后一个区间,然后发出区间范围长度的范围最小查询。从理论上讲,结果是在线算法,它可以执行线性时间预处理并在恒定时间中回答查询,但为方便起见,您可能不会以这种方式实施。

答案 1 :(得分:1)

我们可以在O(nlog(n))中进行排序。首先,用它们的原始索引标记[l,k]中的所有元素。然后,首先根据值对[l,k]中的元素进行排序,然后根据原始索引对元素进行排序。

然后,您可以遍历排序列表,保留currentValue变量,并检查距离相同的相邻值,并在必要时设置minDistance。当您在排序列表中找到新值时,currentValue会更新。

假设我们在第二个例子中有[l,k]范围:

1 2 3 0 3 2 3

我们可以将它们标记为

1(1) 2(2) 3(3) 0(4) 3(5) 2(6) 3(7)

并将它们排序为

0(4) 1(1) 2(2) 2(6) 3(3) 3(5) 3(7)

对此循环,0和1没有范围.2s的最小距离为4,3s的最小距离为2([3,5]或[3,7],具体取决于您是否重置当新的最小距离等于当前的最小距离时minDistance

因此我们得到了

[3,5] in [l,k] or [5,7] in [l,k]

修改

由于您提及某些查询,您可以在O(nlog(n))时间内预处理列表,然后仅对每个查询使用O(n)时间。在循环排序列表时,您将忽略不在[l,k]中的索引。

编辑2

这是解决问题中的澄清,现在该问题总是会有很多查询要运行。我们可以使用动态编程在O(n^2)时间进行预处理,然后在O(1)时间内运行每个查询。

首先,对我上面描述的整个列表执行预处理。然后在O(n)时间内从原始列表到排序列表中形成链接。

我们可以想象:

[l,k] = min([l+1,k], [l,k-1], /*some other sequence starting at l or ending at k*/)

我们有一个基本案例

[l,k] = infinity where l = k

如果[l,k]不是min([l+1,k], [l,k-1]),则它从l开始或以k结束。我们可以采取其中的每一个,查看排序列表并以正确的方向查看相邻元素并检查距离(确保我们在界限内)。我们只需检查2个元素,因此它是一个常数因素。

使用此算法,我们可以运行以下

for l = n downto 1
    for k = l to n
        M[l,k] = min(M[l+1,k], M[l,k-1], sequence starting at l, sequence ending at k)

您还可以将解决方案存储在矩阵中(实际上是金字塔)。然后,当您收到查询[l,k]时,您只需在矩阵中查找即可。