最接近的相等数
Closest equal numbers
假设您有 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]
查询以在具有 log(n)
复杂度的数组中查找 [l, r]SUM
或 [l, r]MIN
。我们可以在这里做一些预处理以适应 o(logn) 吗?
如果第一个数字等于最后一个数字但中间的每个数字在间隔中恰好出现一次,则称间隔 minimal。 11 和 101 是最小的,但 12021 和 10101 不是。
在线性时间(假设恒定时间散列)中,枚举所有的最小间隔。这可以通过保留两个索引 l
和 k
以及将 l
和 k
之间的每个符号映射到其索引的哈希映射来完成。最初,l = 1
和 k = 0
。重复执行以下操作。增加 k
(如果太大,我们停止)。如果新值 k
处的符号在地图中,则将 l
推进到地图值,同时从地图中删除内容。产生间隔 [l, k]
并再次递增 l
。在所有情况下,写 k
作为符号的映射值。
由于最小性,最小间隔按其左右端点以相同方式排序。为了回答查询,我们查找它可能包含的第一个区间和最后一个区间,然后发出区间范围长度的范围最小查询。理论上,结果是 在线 算法执行 线性时间预处理 并在 恒定时间 [=33] 内回答查询=],但为了方便起见,您可能不会那样实现它。
我们可以在 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]
时,你只需在矩阵中查找它。
假设您有 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]
查询以在具有 log(n)
复杂度的数组中查找 [l, r]SUM
或 [l, r]MIN
。我们可以在这里做一些预处理以适应 o(logn) 吗?
如果第一个数字等于最后一个数字但中间的每个数字在间隔中恰好出现一次,则称间隔 minimal。 11 和 101 是最小的,但 12021 和 10101 不是。
在线性时间(假设恒定时间散列)中,枚举所有的最小间隔。这可以通过保留两个索引 l
和 k
以及将 l
和 k
之间的每个符号映射到其索引的哈希映射来完成。最初,l = 1
和 k = 0
。重复执行以下操作。增加 k
(如果太大,我们停止)。如果新值 k
处的符号在地图中,则将 l
推进到地图值,同时从地图中删除内容。产生间隔 [l, k]
并再次递增 l
。在所有情况下,写 k
作为符号的映射值。
由于最小性,最小间隔按其左右端点以相同方式排序。为了回答查询,我们查找它可能包含的第一个区间和最后一个区间,然后发出区间范围长度的范围最小查询。理论上,结果是 在线 算法执行 线性时间预处理 并在 恒定时间 [=33] 内回答查询=],但为了方便起见,您可能不会那样实现它。
我们可以在 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]
时,你只需在矩阵中查找它。