Algorithm 成对向量搜索

Algorithm 成对向量搜索,algorithm,Algorithm,我有一个对向量(datatype=double),其中每对都是(a,b),a小于b。对于一个数字x,我想找出向量中的对数,其中a对于每对a,b,可以进行分解,以便a=+1和b=-1对于特定值有效的范围数。然后in变成了一个简单的O(logn)查找,以查看搜索值包含多少范围。首先,如果您只是对这些对进行简单扫描,您将具有O(n)复杂性!O(n log n)来自排序,对于一次性操作,这只是开销。这甚至可能是最好的方法,如果不重用结果,即使只执行几个查询,也可能比排序更好。确保您允许自己切换出该算法

我有一个对向量(datatype=double),其中每对都是(a,b),a小于b。对于一个数字x,我想找出向量中的对数,其中a对于每对a,b,可以进行分解,以便a=+1和b=-1对于特定值有效的范围数。然后in变成了一个简单的O(logn)查找,以查看搜索值包含多少范围。

首先,如果您只是对这些对进行简单扫描,您将具有O(n)复杂性!O(n log n)来自排序,对于一次性操作,这只是开销。这甚至可能是最好的方法,如果不重用结果,即使只执行几个查询,也可能比排序更好。确保您允许自己切换出该算法

无论如何,让我们考虑一下,你需要做很多查询。然后,一个相对明显的改进步骤是在排序之后不要一步一步地迭代。相反,您可以对下限进行二进制搜索。简单地将序列分成两半。下限可以在任意一半中找到,您可以通过查看分区之间的中间元素来确定。递归,直到找到第一个不可能包含搜索值的元素,因为它的起始值已经更大

至于另一个方向,事情并不是那么容易。仅仅因为您按开始值对范围进行了排序,并不意味着也对结束值进行了排序。此外,匹配的范围和不匹配的范围可以在序列中混合,因此这里您必须执行线性扫描

最后,请注意:

  • 您可以使用多线程并行化此算法
  • 根据外循环中的搜索次数M,还可以将外循环与内循环切换。这意味着,对于每一对输入向量,检查每一个M搜索值是否在范围内。这可能更好,特别是当M搜索适合CPU缓存时

这是段树、二元索引树、区间树中非常典型的样式问题

您必须在阵列上执行两个操作
arr

在一个数组上有两个操作
arr


1. 范围更新
添加(a,b):对于(int i=a;i,除了前面的答案之外,这里有一个建议如何准备范围以优化后续查找。这个想法归结为对所有显著不同的输入值预计算结果,但在值没有显著差异时要明智

为了说明我的意思,让我们来考虑这个范围的范围:

1, 3
1, 8
2, 4
2, 6
准备好的输出结构如下所示:

1, 2 -> 2
2, 3 -> 4
3, 4 -> 3
4, 6 -> 2
6, 8 -> 1
对于范围
1,2
中的任何数字,初始序列中有两个匹配范围。对于范围
2,3
中的任何数字,有四个匹配,等等。请注意,现在有五个范围,因为一些输入范围部分重叠。因为对于每个范围,结束值也是下一个范围,可以优化结束值。结果看起来像一个简单的映射:

1 -> 2
2 -> 4
3 -> 3
4 -> 2
6 -> 1
8 -> 0

请注意,最后一个范围没有后面的值,因此需要显式零。对于第一个范围之前的值,这是隐含的。为了找到值的结果,只需找到小于或等于该值的键。这是一个简单的O(logn)查找。

如果您只有一个
x
,那么按照原始顺序检查每一对的简单方法就是O(N)。当您说查询“大”时,您的意思是您同时要查询多个
x
值吗?或者您只有一个
x
值,并且向量大(您提到了100万对)?@JohnZwinck我有多个x值用于查询,我必须在一个大的向量中查询这个值。你能详细说明或给出一个例子吗?@PunitJain时间不早了,我现在无法给出更全面的答案。但原则是合理的。我提到数据类型是双的,所以我想我不能使用你的解决方案。你能解释一下你的观点吗上下限的二进制搜索实际上,没有。你可以通过搜索你的值
v
不能包含在其中的第一个范围来减少候选值的数量,因为
v
使用二进制搜索。但这对上限不起作用,我想到的方法是有缺陷的。我在上面的答案中修复了这个问题。因此,剩余的复杂性仍然是O(n),虽然运行时间实际上可能会减少。虽然我有一个不同的想法,但我将把它放在第二个答案中。当范围是整数值时,您的答案是完美的,但正如我提到的,数据类型是双精度的,所以我认为我们无法生成输出结构。没有理由不适用于实数。Sry for not帽子,你的方法也适用于实数,问题是我只需要更新我的实数查询过程
1 -> 2
2 -> 4
3 -> 3
4 -> 2
6 -> 1
8 -> 0