力扣刷题👊【1971. 寻找图中是否存在路径】

429 阅读2分钟

「这是我参与2022首次更文挑战的第 9 天,活动详情查看:2022首次更文挑战

题目链接

1971. 寻找图中是否存在路径 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

有一个具有 n个顶点的 双向 图,其中每个顶点标记从 0 到 n - 1(包含 0 和 n - 1)。图中的边用一个二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点对由 最多一条 边连接,并且没有顶点存在与自身相连的边。

请你确定是否存在从顶点 start 开始,到顶点 end 结束的 有效路径 。

给你数组 edges 和整数 n、start和end,如果从 start 到 end 存在 有效路径 ,则返回 true,否则返回 false

测试用例

示例 1:

image.png

输入:n = 3, edges = [[0,1],[1,2],[2,0]], start = 0, end = 2
输出:true
解释:存在由顶点 0 到顶点 2 的路径:
- 012 
- 02

题目分析

整理题目,有 n 个点,编号从 0 开始自增,这些点的关系数据以二维数组的形式存放在 edges 变量中,且这些连线是无向的。给定任意两个点,需要我们确认这两个点是否连通。

个人最习惯的用法就是将二维的关系转化为邻接表的形式,然后在按照广度遍历的方式,从起点开始遍历完所有的点位,如果在遍历的过程中发现了终点,就返回 true,否则返回 false

代码实现

由于点的编号是从 0 开始的连线编码,我们可以用一个长度为 n 的数组来模拟邻接表,数组存储的大致效果如下:

[set, set, ...set]

对应下标上的 set 数据,表示这个点可以连通的其余点

广度遍历的经典操作就是使用一个 set 记录已经访问过的点位,使用一个 queue 记录当前需要遍历的点,每次循环都是从 queue 中取出一个点a,将他关联的点中没有被使用过的点加入到 queue,然后将点a 添加到 set 表示已经访问过

完整的代码如下:

var validPath = function(n, edges, source, destination) {
    // 目的是遍历整个图,确认是否存在点到点的路径
    if (source == destination) return true;
    let arr = new Array(n).fill(0).map(x => new Set());
    edges.forEach(e => {
        arr[e[0]].add(e[1]);
        arr[e[1]].add(e[0]);
    })
    let used = arr[source];
    let que = [...used];
    while (que.length > 0) {
        let curr = que.shift();
        if (curr == destination) return true;
        arr[curr].forEach(x => {
            if (!used.has(x)) {
                que.push(x)
                used.add(x)
            }
        })
    }
    return false;
};

image.png

时间、空间效率双双半百,查看题解,就只有数十条评论+题解,且官方的题解还未发布