【发布时间】:2017-03-16 14:33:43
【问题描述】:
我的代码花费了 40% 的时间来搜索未排序的向量。更具体地说,搜索函数my_search 重复接收长度为N 的单个未排序向量,其中N 可以取10 到100,000 之间的任何值。与每个元素相关的权重变化相对较小(例如 [0.8, 0.81, 0.85, 0.78, 0.8, 0.7, 0.84, 0.82, ...])。
算法my_search 首先将每个对象的所有权重相加,然后对N 元素(与向量的长度一样多)进行平均采样并替换。该算法与
int sum_of_weight = 0;
for(int i=0; i<num_choices; i++) {
sum_of_weight += choice_weight[i];
}
int rnd = random(sum_of_weight);
for(int i=0; i<num_choices; i++) {
if(rnd < choice_weight[i])
return i;
rnd -= choice_weight[i];
}
来自this post。
我可以在搜索之前对向量进行排序,但需要花费 O(N log N) 的时间(取决于使用的排序算法),我怀疑(但可能是错误的,因为我没有尝试过)我会获得更多时间,尤其是在权重变化不大的情况下。
另一种解决方案是存储一系列点之前有多少重量的信息。例如,在对向量求和时,每 N/10 个元素,我可以存储已经求和了多少权重的信息。然后,我可以先将rnd 与这 10 个断点进行比较,然后只在向量总长度的十分之一中进行搜索。
- 这是一个好的解决方案吗?
- 我描述的过程有名称吗?
- 如何根据
N估算要存储的正确断点数? - 有更好的解决方案吗?
【问题讨论】:
-
如果重复搜索同一个列表,排序命中的 N log (N) 会越来越有吸引力。假设您排序一次并缓存。
-
@user4581301 OP 说他反复收到未排序的向量
-
@smac89 OP 没有说明未排序的向量是否重复。 OP 有两种选择:强加顺序或线性搜索。
-
更好的解决方案是创建第二个长度为 N 的数组,并将每个部分和存储在该数组中。然后,您可以使用二分查找来查找部分总和超过
rnd的索引。实际上,如果您只关心索引,那么您甚至不需要第二个数组。只需修改输入数组,使其包含部分和。 -
choice_weight 的元素是什么类型的?如果是 double/float,则应将 sum_of_weight 定义为相同类型(但不是整数)。
标签: c++ algorithm sorting search