在工作面试中问了这个问题。
假设您要移动,并拥有一系列便利设施 希望可以方便地从新家访问。您已经找到一个 您喜欢的社区,其中每个街区都有零个或多个便利设施。 您将如何选择最远的街区 到您列表中任何便利设施的距离都最小化了?
例如,假设您的列表包含{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
是什么指示。
答案 0 :(得分:0)
是的,我们可以在O(n * k log n)中做到,其中n是街区数量,k是便利设施数量
便利设施的列表很小,因此创建ArrayList 每种便利设施,并存储该便利设施所在的街区位置。
即使用您提供的示例:
因此,现在我们可以遍历所有块并使用lower_bound(二进制搜索) 为每种所需的便利设施找到具有所需便利设施的最近街区
然后选择一个与所需设施的距离最短的街区。
答案 1 :(得分:0)
解决方案是包含所有便利设施的最短的子块数组。请注意,最左边的区域的便利设施必须只出现一次;最右边也一样。居住的街区就在中间。
两个指针技术非常适合。
具有k
个计数器的数组,每个计数器在当前窗口中都为一个,将其初始化为全零。将两个指针left
和right
放入块数组;最初,两者都指向数组的开头。然后执行步骤
加速:前进right
指针,计算它经过的便利设施,直到遇到每种便利设施为止。
从左侧修剪:只要两个计数器都没有到达left
,就向前移动0
指针,使计数器递减。您有一个临时的解决方案;记录下来。
在循环中,
left
次,使相关计数器递减。其中一些变为0。left
。right
,直到再次填充所有计数器。这是另一种尝试性的解决方案,请保持最佳状态。假设任何给定的块都没有太多便利设施,那么它将在O(n) time, and
O(k)`空间中运行。
正确性证明留作练习。