「这是我参与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:
输入:n = 3, edges = [[0,1],[1,2],[2,0]], start = 0, end = 2
输出:true
解释:存在由顶点 0 到顶点 2 的路径:
- 0 → 1 → 2
- 0 → 2
题目分析
整理题目,有 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;
};
时间、空间效率双双半百,查看题解,就只有数十条评论+题解,且官方的题解还未发布