AlgoMooc
你已开通华为OD训练营权益,还差最后一步——完成入营激活(兑换课程 + 加飞书 + 登记服务群),即可解锁全部课程与专属服务。去激活 →
← OD 20 天课程

华为 OD 训练营 · 题解精讲

LeetCode1334. 阈值距离内邻居最少的城市

LeetCode1334. 阈值距离内邻居最少的城市

题目描述

有 n 个城市,按从 0 到 n-1 编号。给你一个边数组 edges,其中 edges[i] = [from(i), to(i), weight(i)] 代表 from(i) 和 to(i)两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold。 返回在路径距离限制为 distanceThreshold 以内可到达城市最少的城市。如果有多个这样的城市,则返回编号最大的城市。 注意,连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。

示例 1: CFzrbRBQ0o0gfIxDMgDctGlsne6.png

输入:n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4 输出:3 解释:城市分布图如上。 每个城市阈值距离 distanceThreshold = 4 内的邻居城市分别是: 城市 0 -> [城市 1, 城市 2] 城市 1 -> [城市 0, 城市 2, 城市 3] 城市 2 -> [城市 0, 城市 1, 城市 3] 城市 3 -> [城市 1, 城市 2] 城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市,但是我们必须返回城市 3,因为它的编号最大。 示例 2: EuShbeSdlo5SKXxV5gTcXxdanUe.png

输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2 输出:0 解释:城市分布图如上。 每个城市阈值距离 distanceThreshold = 2 内的邻居城市分别是: 城市 0 -> [城市 1] 城市 1 -> [城市 0, 城市 4] 城市 2 -> [城市 3, 城市 4] 城市 3 -> [城市 2, 城市 4] 城市 4 -> [城市 1, 城市 2, 城市 3] 城市 0 在阈值距离 2 以内只有 1 个邻居城市。

提示: 2 <= n <= 100 1 <= edges.length <= n * (n - 1) / 2 edges[i].length == 3 0 <= from(i) < to(i) < n 1 <= weight(i), distanceThreshold <= 10^4 所有 (from(i), to(i)) 都是不同的。

题目解析

本题的设问是,希望找到在阈值距离范围内能到达城市最少的城市编号。

这意味着,这个最短路问题并不是求特定起点到特定终点的距离,而是要考虑不同的起点和不同的终点。

因此是一个全源最短路径问题,应该使用Floyd算法来解决。

关于全源最短路问题的Floyd算法的详细解释,可以查看2024/08/03 真题讲解(最短路问题Floyd算法专题)

参考代码

参考代码

# 题目:LeetCode1334. 阈值距离内邻居最少的城市
# 作者:闭着眼睛学数理化
# 算法:最短路问题-Floyd算法
# 代码看不懂的地方,请直接在群上提问


class Solution:
    def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int:
        grid = [n * [inf] for _ in range(n)]
        # 初始化,grid[a][b]表示从a到b的最短路径
        for a, b, w in edges:
            grid[a][b], grid[b][a] = w, w
        # grid数组的对角线均为0,表示从节点i到达其自身的路径为0
        for i in range(n):
            grid[i][i] = 0
        
        # 枚举所有中间点(插点)
        for mid in range(n):
            # 枚举起始点
            for start in range(n):
                # 枚举终点
                for end in range(n):
                    # 动态转移方程:如果直接从start到end的最短路径,不如先从start再到mid再到end的距离短
                    # 则更新grid[start][end]。
                    if grid[start][end] > grid[start][mid] + grid[mid][end]:
                        grid[start][end] = grid[start][mid] + grid[mid][end]
                        grid[end][start] = grid[start][mid] + grid[mid][end]

        ans, min_num = -1, inf
        # 再次遍历所有节点i
        for i in range(n):
            # 计算从节点i出发,其最短距离小于阈值distanceThreshold的其他节点数目
            # -1表示刨除其自身的影响,本题其实不-1也可以
            num = sum(dis <= distanceThreshold for dis in grid[i]) - 1
            if min_num >= num:
                ans = i
                min_num = num
        return ans