最小化到最远点的距离

时间:2019-05-02 06:19:32

标签: algorithm graph-theory graph-algorithm

在工作面试中问了这个问题。

  

假设您要移动,并拥有一系列便利设施   希望可以方便地从新家访问。您已经找到一个   您喜欢的社区,其中每个街区都有零个或多个便利设施。   您将如何选择最远的街区   到您列表中任何便利设施的距离都最小化了?

     

例如,假设您的列表包含{school,杂货店}和街区   如下:

     

1:餐厅,杂货店

     

2:电影院

     

3:学校

     

4:

     

5:学校

     

理想的选择是第2块,这样到   杂货店和最近的学校分别是1家。住在1或3街区   会使距离之一变为零,而使另一距离变为2。

我想出了一个朴素的解决方案,如下面的伪代码所示:

max = minus infinity
min = plus infinity    

for r in requirements:
  for i in blocks:
    for j in blocks:
      if j.amenities contains r:
        max = maximum {max, dist(i, j)}
    if max < min:
      live_at = i

如果n是块数,则假设要求列表比O(n^2)小,则此算法的时间复杂度为n。我们可以做得更好吗?

This的问题似乎很相似,尽管答案对我来说还不清楚。它指的是纸张,以“在中心c画一个圆”开头,没有任何c是什么指示。

2 个答案:

答案 0 :(得分:0)

是的,我们可以在O(n * k log n)中做到,其中n是街区数量,k是便利设施数量

便利设施的列表很小,因此创建ArrayList 每种便利设施,并存储该便利设施所在的街区位置。

即使用您提供的示例:

  • A [“餐厅”] = {1}
  • A [“食品杂货”] = {1}
  • A [“电影院”] = {2}
  • A [“学校”] = {3,5}

因此,现在我们可以遍历所有块并使用lower_bound(二进制搜索) 为每种所需的便利设施找到具有所需便利设施的最近街区

然后选择一个与所需设施的距离最短的街区。

答案 1 :(得分:0)

解决方案是包含所有便利设施的最短的子块数组。请注意,最左边的区域的便利设施必须只出现一次;最右边也一样。居住的街区就在中间。

两个指针技术非常适合。

具有k个计数器的数组,每个计数器在当前窗口中都为一个,将其初始化为全零。将两个指针leftright放入块数组;最初,两者都指向数组的开头。然后执行步骤

  • 加速:前进right指针,计算它经过的便利设施,直到遇到每种便利设施为止。

  • 从左侧修剪:只要两个计数器都没有到达left,就向前移动0指针,使计数器递减。您有一个临时的解决方案;记录下来。

  • 在循环中,

    • 提前left次,使相关计数器递减。其中一些变为0。
    • 从左侧修剪:只要没有其他计数器变为0,就继续前进left
    • 前进right,直到再次填充所有计数器。这是另一种尝试性的解决方案,请保持最佳状态。
    • 保持循环,直到无法再正确指针。

假设任何给定的块都没有太多便利设施,那么它将在O(n) time, and O(k)`空间中运行。

正确性证明留作练习。