这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
题目
存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号。
给你一个数组 graph 表示这个图。其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。
返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。
示例 1:
输入:graph = [[1,2,3],[0],[0],[0]] 输出:4 解释:一种可能的路径为 [1,0,2,0,3] 示例 2:
输入:graph = [[1],[0,2,4],[1,3,4],[2],[1,2]] 输出:4 解释:一种可能的路径为 [0,1,4,2,3]
解题思路
- 因为这题可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。所以我们不能像普通BFS的使用set进行去重,我们需要使用到达某一节点时路径上经过的节点情况去进行去重
- 因为1 <= n <= 12,所以我们只需要使用一个int类型去记录路径下经过的节点
- 再使用广度优先搜索,队列中的元素,分别为
- 当前位于的节点编号;
- 一个长度为 n 的二进制数,表示每一个节点是否经过。如果第 i 位是 1,则表示节点 i 已经过,否则表示节点 i 未经过;
- 表示到当前节点为止经过的路径长度。 找出第一条包含所有节点的路径
代码
class Solution {
public int shortestPathLength(int[][] graph) {
int n=graph.length;
boolean[][] check=new boolean[n][1<<n];
Queue<int[]> queue=new LinkedList<>();
for (int i = 0; i < n; i++) {
queue.add(new int[]{i,0,1<<i});
check[i][1<<i]=true;
}
while (!queue.isEmpty())
{
int[] cur = queue.poll();
if ((1<<n)-1==cur[2])
return cur[1];
for (int g : graph[cur[0]]) {
int nx=cur[2]|(1<<g);
if (!check[g][nx])
{
queue.add(new int[]{g,cur[1]+1,nx});
check[g][nx]=true;
}
}
}
return 0;
}
}