开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第27天,点击查看活动详情
刷题的日常-2022年12月19号
一天一题,保持脑子清爽
寻找图中是否存在路径
来自leetcode的 1971 题,题意如下:
有一个具有 n 个顶点的 双向 图,其中每个顶点标记从 0 到 n - 1(包含 0 和 n - 1)。图中的边用一个二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点对由 最多一条 边连接,并且没有顶点存在与自身相连的边。
请你确定是否存在从顶点 source 开始,到顶点 destination 结束的 有效路径 。
给你数组 edges 和整数 n、source 和 destination,如果从 source 到 destination 存在 有效路径 ,则返回 true,否则返回 false 。
理解题意
通过题意,我们可以将信息整理如下:
- 题目给出一个数组代表连线
- 一个source表示出发点,destination代表目标点
- 如果从出发点沿着路径一直走,能够达到目标点,返回true,否则返回false
做题思路
题目给出的连线是双向的,所以我们需要将双向的连线改为单向的,将所有的单向连线保存起来,然后从开始节点出发,一直往后走,如果能够碰到目标节点,返回true。这里需要注意的是,如果没有连线,需要做特殊判断,如果开始节点和目标节点是一样的,返回true,否则返回false。
需要注意的问题是,如果出现环形路径,要进行判断,否则会陷入死循环。
代码实现
代码实现如下:
public class Solution {
public boolean validPath(int n, int[][] edges, int source, int destination) {
if (edges.length == 0) {
return source == destination;
}
HashMap<Integer, List<int[]>> sourceMap = new HashMap<>();
for (int[] edge : edges) {
List<int[]> tmp = sourceMap.computeIfAbsent(edge[0], o -> new ArrayList<>());
tmp.add(edge);
edge = new int[]{edge[1], edge[0]};
tmp = sourceMap.computeIfAbsent(edge[0], o -> new ArrayList<>());
tmp.add(edge);
}
List<int[]> sList = sourceMap.get(source);
for (int[] start : sList) {
if (match(start, destination, sourceMap)) {
return true;
}
}
return false;
}
private boolean match(int[] start, int destination, HashMap<Integer, List<int[]>> sourceMap) {
Queue<int[]> queue = new ArrayDeque<>(sourceMap.size());
queue.add(start);
Set<int[]> set = new HashSet<>();
while (!queue.isEmpty()) {
start = queue.poll();
if (set.contains(start)) {
continue;
}
set.add(start);
if (start[1] == destination) {
return true;
}
List<int[]> tmp = sourceMap.get(start[1]);
if (tmp != null) {
queue.addAll(tmp);
}
}
return false;
}
}