笛卡尔平面中的点对之间的距离

时间:2015-04-19 17:18:00

标签: algorithm geometry

我最近在Foursquare的采访中被问到以下问题。我无法对此进行编码。

我们给出N个点(xi,yi),其中1 <= i <= N,并且两个数字a和b,使得两个点(x1,y1)和(x2,y2)之间的距离是max(a * | x1-x2 |,b * | y1-y2 |),我们如何计算每对点之间的距离之和?

点数N是一个很高的数字。

任何人都可以帮忙解决这个问题吗?请解释算法,除了遍历所有点对的蛮力之外。

2 个答案:

答案 0 :(得分:6)

首先重新调整轴,以消除ab因素。定义x' = a * x, y' = b * y'。然后距离是:

max(a*|x1-x2|,b*|y1-y2|) =
max(|a*x1-a*x2|,|b*y1-b*y2|) =
max(|x'1-x'2|,|y'1-y'2|)

其次,将坐标系旋转45度,将其更改为Taxicab geometry。定义s = (x' + y')/2, t = (x' - y')/2。然后我们有x' = s + t, y' = s - t

然后我们可以再次重写距离的定义:

max(|x'1-x'2|,|y'1-y'2|) =
max(|s1 + t1 - s2 - t2|,|s1 - t1 - s2 + t2|) =
max(|(s1 - s2) + (t1 - t2)|,|(s1 - s2) - (t1 - t2)|) =
|s1 - s2| + |t1 - t2|
-- last equation comes from the fact that max(|a + b|, |a - b|) = |a| + |b|

根据这个定义,我们可以分别沿着s轴和t轴分别对距离进行求和,并添加结果。

解决这个问题的一维版本非常简单。您可以沿轴对点进行排序。然后,基于0的i - 和i+1 - 点之间的每个段将贡献(i + 1) * (N - i - 1) * distance。这足以将这些值相加。

整体解决方案需要O(n lg n),因为它需要对点进行两次排序。

答案 1 :(得分:1)

我们想要计算

sum_i sum_j max(a |xi - xj|, b |yi - yj|).

通过映射xi' = a xiyi' = b yi以及计算

来简化问题
sum_i sum_j max(|xi' - xj'|, |yi' - yj'|).

通过映射ui = (xi + yi)/2vi = (xi - yi)/2以及计算

来简化问题
sum_i sum_j (|ui - uj| + |vi - vj|)
    = sum_i sum_j |ui - uj| + sum_i sum_j |vi - vj|.

要解决时间O(n log n)中的第一个子问题,这里有一些Python。

def one_d(us):
    us = sorted(us)
    return sum((2 * i - (len(us) - 1)) * u for (i, u) in enumerate(us))