在欧几里得平面中给出N个点。对于每个点,找到其自身与其他点之间的最小距离

时间:2019-03-29 16:01:28

标签: math coordinates

问题很简单:n点在欧几里得平面中由其坐标给出。对于每个点,您应该使用欧几里得距离找到其自身与其他任何点之间的最小距离。该最小距离称为该点的半径。对于每一点,我们应该返回两件事:

  1. 半径(r)。

  2. 欧氏距离小于或等于2*r的点数(不包括自身)。

输入限制:

1 <= number of coordinates <= 30000
0 <= x,y <= 10000

好吧,我已经在o(n^2)中做到了。有谁有更好的解决方案?

示例:

1. n=3
(0,0)
(0,0)
(3,4)

output-
(0.00 1)
(0.00 1)
(5.00 2)

2. n=5
(5,3)
(7,8)
(0,9)
(3,1)
(4,4)

output-
(1.41 2)
(5.00 4)
(6.40 4)
(2.83 2)
(1.41 1)

1 个答案:

答案 0 :(得分:0)

首先,认识到距离是对称的。 ij的距离与ji的距离相同。总共有n*(n-1)/2条距离可以计算。

如果使用以下循环对它们进行预计算,则任何进一步的处理(如扫描最近的处理)都将非常快。

// n = number of points
distances=new float[n*(n-1)/2];
int index = 0;
for (int i = 0; i<n-1; i++)
{
    for (int j = i+1; j<n; j++)
    {
        // This is by far the most expensive operation to make:
        distances[index++]=Vector2.Distance(Points[i], Points[j]);                    
    }
}

不要很快获得ij两点之间的距离。

class PointCloud
{

    int n;
    float[] distances;

    float GetDistance(int i, int j)
    {
        if(i==j) return 0;
        if(i>j) return GetDistance(j ,i);
        int index = -i*(i-2*n+1)/2+(j-i)-1;
        return distances[index];
    }
}

计算index = -i*(i-2*n+1)/2+(j-i)-1解释如下。我们仅存储距离的矩阵的上三角值。每行i都有row=n-i-1个值,第一个值(最接近对角线)的索引是start=sum(n-t-1,t=0,i-1) = -i*(i-2*n+1)/2j列的索引为index = start + j- i -1,是j与对角线旁边的列之间的位置差。

例如,n=4仅存储6个值。每对距离数组的索引计算如下:

  j=0      j=3
| *  0  1  2 | i=0
| 0  *  3  4 |
| 1  3  *  5 |
| 2  4  5  * | i=3

因此,要获取i=1j=3之间的距离,上面的index=4distances[index]是需要的值。请注意,-i*(i-2*n+1)/2+(j-i)-1 = -1*(1-2*4+1)/2+(3-1)-1 = 4

-参考文章:https://stackoverflow.com/a/9040526/380384用于打包形式的对称矩阵,但是用于存储上三角值对角线的对称矩阵。因此,类似但不精确。

从本质上讲,与在所有对上使用双嵌套循环的简单方法相比,上述方法将处理减少了一半。