假设您有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]MIN
或log(n)
。我们可以在这里进行一些预处理以适应o(logn)吗?
答案 0 :(得分:1)
如果第一个数字等于最后一个数字,则调用间隔 minimal 但是间隔中的每个数字只出现一次。 11和101是最小的,但12021和10101不是。
在线性时间内(假设恒定时间散列),枚举所有最小间隔。这可以通过保留两个索引l
和k
以及将l
和k
之间的每个符号映射到其索引的哈希映射来完成。最初是l = 1
和k = 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]
时,您只需在矩阵中查找即可。