问题很简单:n
点在欧几里得平面中由其坐标给出。对于每个点,您应该使用欧几里得距离找到其自身与其他任何点之间的最小距离。该最小距离称为该点的半径。对于每一点,我们应该返回两件事:
半径(r
)。
欧氏距离小于或等于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)
答案 0 :(得分:0)
首先,认识到距离是对称的。 i
到j
的距离与j
到i
的距离相同。总共有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]);
}
}
不要很快获得i
和j
两点之间的距离。
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)/2
。 j
列的索引为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=1
和j=3
之间的距离,上面的index=4
和distances[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用于打包形式的对称矩阵,但是用于存储上三角值和对角线的对称矩阵。因此,类似但不精确。
从本质上讲,与在所有对上使用双嵌套循环的简单方法相比,上述方法将处理减少了一半。