我正在通过算法学习测试,并且发现了几天我无法处理的问题。所以我在这里寻求帮助。
对于给定的两个不相交的平面集:
G={(x_1^G, y_1^G), (x_2^G, y_2^G), ..., (x_n^G, y_n^G)}
D={(x_1^D, y_1^D), (x_2^D, y_2^D), ..., (x_n^D, y_n^D)}
Where for every 1 <= i, j <= n we have y_i^D < y_j^G, so G is above D.
找到一个有效的算法
counts the distance between them
定义为:
d(G,D) = min{ d(a,b): a \in G and b\in D },
where d(a,b) = |x_a - x_b| + |y_a - y_b|
O(n ^ 2)是微不足道的,所以它不是答案。
我希望解决方案不是太难,因为在测试之前它是从材料到审查。有人可以帮忙吗?
我认为这似乎是一个常见问题的特例。但如果是特殊情况,那么解决方案可能会更容易吗?
答案 0 :(得分:1)
在O(n log n)时间内有几种不同的方法可以做到这一点。
一:计算G点的曼哈顿距离Voronoi diagram,并基于此构建点位置数据结构。这需要O(n log n)时间。对于每个D点,使用点位置数据结构找到最接近的G点。这需要每D点O(log n)时间。取你刚刚找到的对之间的距离的最小值,这就是你的答案。
二:你可以使Fortune's algorithm适应这个问题;只需为D和G点保留单独的二叉树。有点讨厌描述。
下一个想法计算无穷大范数最近对的距离,即max(| x1-x2 |,| y1-y2 |)。您可以将问题倾斜45度(替换为u = x-y,v = x + y)以使其成为适当的形式。
三个(两个变量):按y坐标对所有点进行排序。保持d,到目前为止看到的最近一对之间的距离。我们将从上到下扫描一条线,保留两个二叉搜索树,一个G点和一个D点。当一个点在扫描线上方或更远时,我们将其从二叉搜索树中删除。当扫描线首次遇到一个点时,比如一个D点,我们(1)检查G二叉搜索树,看它是否有任何x坐标在新点的d内的元素,必要时更新d, (2)将新点插入D的二叉搜索树。每个点仅导致恒定数量的二进制搜索树操作加上恒定数量的附加工作,因此扫描为O(n log n)。这种情况也不足为奇,因此我们的整体时间复杂度也是如此。
你可能也可以根据类似的想法制定分而治之的策略。