我有2组节点 - 设置A和设置B.每组大小为25,000。
我得到一个百分比(比方说20%)。我需要找到最小距离,使得集合A中20%的节点都在集合B中任何节点的距离之内。
解决方案:
找到最接近集合B中任何节点的集合A的20%。答案是该集合中距离集合B中任何节点最远的20%的节点。
暴力解决方案:
foreach (Node a in setA)
{
a.ShortestDistance = infinity;
foreach (Node b in setB)
{
if (a.DistanceTo(b) < a.ShortestDistance)
{
a.ShortestDistance = a.DistanceTo(b);
}
}
}
setA.SortByShortestDistance();
return setA[setA.Size * 0.2];
这样可行,但需要的时间是疯了。 (O(n ^ 2 +排序)我认为?)
我怎样才能加快速度?如果可能,我想打O(n)。
答案 0 :(得分:1)
以下是一种可能提高速度的算法: -
- 将你的(纬度,长度)对转换为笛卡尔坐标中的(x,y,z),以地心为原点
- 笛卡尔坐标系中(x,y,z)之间的距离与球坐标中的实际距离下限。
- 构建以分隔3d trees for setA和setB。
- 对于setA中的每个节点a,在setB的3d树中搜索最近邻居,平均情况为O(logN)。
- 那么最近邻居的距离就是距离最近邻居的距离。
- 然后按照你的意思对setA进行排序。
醇>
时间复杂度: -
平均情况: O(n*logn)
最糟糕的情况: O(n^2)
答案 1 :(得分:1)
您可以选择两个中较小的一组并从中构建一个结构来回答最近邻查询 - http://en.wikipedia.org/wiki/Cover_tree不会对基础指标做出很多假设,因此它应该适用于hasrsine / great circle。
执行此操作后,最简单的方法是获取较大集合中的每个成员,在较小集合中找到它的最近邻居,然后排序或http://en.wikipedia.org/wiki/Quickselect距离。如果您将查找操作修改为提前返回而没有找到任何内容,如果最近的对象必须超过阈值距离,并且您对距离有了大致的了解,则可能会节省一些时间。
您可以通过事先对两组中的随机样本执行相同的操作来获得一个粗略的想法。如果你的猜测有点太高,你只需要几个最近的邻居来进行排序。如果你的猜测有点太低,你只需要为那些最近的邻居操作提前返回而没有找到任何东西的那些点重复查找操作。