两个城市间路径的最小分数

62 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

题目描述

给你一个正整数 n ,表示总共有 n 个城市,城市从 1 到 n 编号。给你一个二维数组 roads ,其中 roads[i] = [ai, bi, distancei] 表示城市 ai 和 bi 之间有一条 双向 道路,道路距离为 distancei 。城市构成的图不一定是连通的。

两个城市之间一条路径的 分数 定义为这条路径中道路的 最小 距离。

城市 1 和城市 n 之间的所有路径的 最小 分数。

注意:

  • 一条路径指的是两个城市之间的道路序列。
  • 一条路径可以 多次 包含同一条道路,你也可以沿着路径多次到达城市 1 和城市 n 。
  • 测试数据保证城市 1 和城市n 之间 至少 有一条路径。

示例 1:

输入: n = 4, roads = [[1,2,9],[2,3,6],[2,4,5],[1,4,7]]
输出: 5
解释: 城市 1 到城市 4 的路径中,分数最小的一条为:1 -> 2 -> 4 。这条路径的分数是 min(9,5) = 5 。
不存在分数更小的路径。

示例 2:

输入: n = 4, roads = [[1,2,2],[1,3,4],[3,4,7]]
输出: 2
解释: 城市 1 到城市 4 分数最小的路径是:1 -> 2 -> 1 -> 3 -> 4 。这条路径的分数是 min(2,2,4,7) = 2

提示:

  • 2 <= n <= 10^5
  • 1 <= roads.length <= 10^5
  • roads[i].length == 3
  • 1 <= ai, bi <= n
  • ai != bi
  • 1 <= distancei <= 10^4
  • 不会有重复的边。
  • 城市 1 和城市 n 之间至少有一条路径。

思路分析

题目会给我们两个参数n和roads,n表示城市的数量,roads为城市间的路径信息,我们需要找到在城市 1 和城市 n 之间的所有路径的 最小 分数。简单来说就是要找到一个包含1和n的连通块中的路径最小分数,因为城市 1 和城市 n 之间至少有一条路径,所以包含1的连通块也一定包含n,所以我们可以直接进行递归搜索遍历即可。

  • 1、使用哈希表记录每个城市的路径

遍历路径数组,记录每个城市的路径情况,因为这里的路径是双向的,所以路径两端的城市都应该记录,并使用哈希表记录两个城市连接路径的分数,便于后续取值。

 let map = {};
 let count = {};
 for(let i = 0; i < roads.length; i++){
    if(!map[roads[i][0]]) map[roads[i][0]] = [];
    map[roads[i][0]].push(roads[i][1]);
    if(!map[roads[i][1]]) map[roads[i][1]] = [];
    map[roads[i][1]].push(roads[i][0]);
    count[roads[i][0]+'-'+roads[i][1]] = roads[i][2];
    count[roads[i][1]+'-'+roads[i][0]] = roads[i][2];
 }
  • 2、递归遍历获取最小路径分数

这里需要注意将遍历过的路径记录起来,后面再次遍历到的时候可以直接跳过,遍历搜索然后维护记录最小的路径分数即可。

const visited = {};
const search = (i,last)=>{
    if(visited[last + '-' + i]) return;
    if(visited[i + '-' + last]) return;
     if(i != last){
        res = Math.min(res,count[i+'-'+last]);
        res = Math.min(res,count[last+'-'+i]);
     }
     visited[last + '-' + i] = true;
     visited[i + '-' + last] = true;
     for(let j = 0; j < map[i].length; j++){
         search(map[i][j],i);
     }
}

AC代码

完整AC代码如下:

/**
 * @param {number} n
 * @param {number[][]} roads
 * @return {number}
 */
 var minScore = function(n, roads) {
     let res = roads[0][2];
     let map = {};
     let count = {};
     for(let i = 0; i < roads.length; i++){
        if(!map[roads[i][0]]) map[roads[i][0]] = [];
        map[roads[i][0]].push(roads[i][1]);
        if(!map[roads[i][1]]) map[roads[i][1]] = [];
        map[roads[i][1]].push(roads[i][0]);
        count[roads[i][0]+'-'+roads[i][1]] = roads[i][2];
        count[roads[i][1]+'-'+roads[i][0]] = roads[i][2];
     }
     const visited = {};
     const search = (i,last)=>{
        if(visited[last + '-' + i]) return;
        if(visited[i + '-' + last]) return;
         if(i != last){
            res = Math.min(res,count[i+'-'+last]);
            res = Math.min(res,count[last+'-'+i]);
         }
         visited[last + '-' + i] = true;
         visited[i + '-' + last] = true;
         for(let j = 0; j < map[i].length; j++){
             search(map[i][j],i);
         }
     }
     search(1,1);
     return res;
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。