理想火车站定位
问题描述
小F是A市的市长,正在计划在A市新建一个火车站以方便市民的日常出行。市区内的街道布局十分规整,形成网格状。从一个位置[x1, y1]到另一个位置[x2, y2]的距离计算方法为 |x1 - x2| + |y1 - y2|,即曼哈顿距离。
在初步考察后,市政府列出了M个可能的火车站建设点。为了使得市民到火车站的总旅行时间最短,小F希望选出一个最优位置作为火车站的地址。
请你帮助小F计算出哪一个位置最适合建设新火车站。
N: 市民的总人数。M: 可建设火车站的备选位置数。citizens: 一个列表,每个元素是一个元组[x_i, y_i],表示第i位市民的居住位置。locations: 一个列表,每个元素是一个元组[p_i, q_i],表示第i个备选的火车站位置。
如果有多个火车站最优,那么选择第一次出现的那个。
测试样例
样例1:
输入:
n = 4, m = 3, citizens = [[-1, -1], [-1, 1], [1, -1], [1, 1]], locations = [[3, 2], [1, 0], [0, 0]]输出:[1, 0]
样例2:
输入:
n = 2, m = 2, citizens = [[0, 0], [0, 4]], locations = [[0, 2], [0, 3]]输出:[0, 2]
样例3:
输入:
n = 3, m = 1, citizens = [[10, 10], [20, 20], [30, 30]], locations = [[15, 15]]输出:[15, 15]
样例4:
输入:
n = 5, m = 3, citizens = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], locations = [[4, 5], [6, 7], [8, 9]]输出:[4, 5]
样例5:
输入:
n = 6, m = 2, citizens = [[10, 10], [20, 20], [30, 30], [40, 40], [50, 50], [60, 60]], locations = [[35, 35], [45, 45]]输出:[35, 35]
解题思路
问题理解
我们需要在给定的 M 个备选火车站位置中,选择一个位置,使得所有市民到该位置的总曼哈顿距离最小。曼哈顿距离的计算公式为 |x1 - x2| + |y1 - y2|。
数据结构选择
- 市民位置:使用一个列表
citizens,其中每个元素是一个元组[x_i, y_i],表示第i位市民的居住位置。 - 火车站位置:使用一个列表
locations,其中每个元素是一个元组[p_i, q_i],表示第i个备选的火车站位置。
算法步骤
-
初始化:
- 初始化一个变量
min_total_distance来存储最小的总距离,初始值为一个很大的值(例如float('inf'))。 - 初始化一个变量
best_location来存储最优的火车站位置,初始值为[-1, -1]。
- 初始化一个变量
-
遍历所有火车站位置:
- 对于每个火车站位置
loc,计算它到所有市民的总距离。
- 对于每个火车站位置
-
计算总距离:
- 对于每个市民位置
citizen,计算它到当前火车站位置loc的曼哈顿距离,并累加到total_distance。
- 对于每个市民位置
-
更新最优位置:
- 如果当前的总距离
total_distance小于min_total_distance,则更新min_total_distance和best_location。
- 如果当前的总距离
-
返回结果:
- 遍历完所有火车站位置后,返回
best_location。
- 遍历完所有火车站位置后,返回
Python3代码(通过豆包Marscode测试)
def solution(n, m, citizens, locations):
# 初始化最小距离为一个很大的值
min_total_distance = float('inf')
# 初始化最优位置为 [-1, -1]
best_location = [-1, -1]
# 遍历所有火车站位置
for loc in locations:
total_distance = 0
# 计算当前位置到所有市民的总距离
for citizen in citizens:
# 计算曼哈顿距离
distance = abs(loc[0] - citizen[0]) + abs(loc[1] - citizen[1])
total_distance += distance
# 如果当前总距离小于最小总距离,更新最小总距离和最优位置
if total_distance < min_total_distance:
min_total_distance = total_distance
best_location = loc
return best_location
关键步骤
- 初始化最小距离和最优位置:使用
float('inf')初始化最小距离,使用[-1, -1]初始化最优位置。 - 遍历所有火车站位置:使用
for loc in locations遍历每个火车站位置。 - 计算当前位置到所有市民的总距离:使用
for citizen in citizens遍历每个市民,计算曼哈顿距离并累加到total_distance。 - 更新最小总距离和最优位置:如果当前总距离小于最小总距离,更新最小总距离和最优位置。
时间复杂度
当前代码的主要时间复杂度来自于两个嵌套的循环:
- 外层循环:遍历所有的火车站位置,假设有
M个火车站位置。 - 内层循环:对于每个火车站位置,遍历所有的市民,假设有
N个市民。
因此,总的时间复杂度为 O(M * N),其中 M 是火车站位置的数量,N 是市民的数量。
空间复杂度
当前代码的空间复杂度主要来自于以下几个方面:
- 输入数据:
citizens和locations列表,假设citizens列表的大小为N,locations列表的大小为M。 - 变量:
min_total_distance、best_location、total_distance等变量,这些变量占用的空间是常数级别的。
因此,总的空间复杂度为 O(N + M),其中 N 是市民的数量,M 是火车站位置的数量。
总结
- 时间复杂度:
O(M * N) - 空间复杂度:
O(N + M)
心得体会
在解答这道题时,需要注意以下几点:
- 曼哈顿距离的计算:确保使用
|x1 - x2| + |y1 - y2|公式正确计算曼哈顿距离,避免使用其他距离计算方法。 - 遍历所有火车站位置:需要遍历所有可能的火车站位置,计算每个位置到所有市民的总距离,确保每个位置都被正确计算。
- 更新最优位置:在遍历过程中,如果发现某个位置的总距离小于当前的最小总距离,及时更新最小总距离和最优位置。
- 初始化变量:初始化最小总距离为一个很大的值(例如
float('inf')),初始化最优位置为一个无效值(例如[-1, -1]),以确保在第一次比较时能够正确更新。 - 返回结果:遍历完所有火车站位置后,返回最优位置。
- 边界条件:确保代码能够处理边界条件,例如只有一个市民或一个火车站位置,以及所有市民和火车站位置都在同一行或同一列的情况。
通过遵循这些注意事项,可以确保代码正确计算最优火车站位置,并处理各种边界情况。