给你一个有 n
个节点的 有向无环图(DAG),请你找出所有从节点 0
到节点 n-1
的路径并输出(不要求按特定顺序)
二维数组的第 i
个数组中的单元都表示有向图中 i
号节点所能到达的下一些节点,空就是没有下一个结点了。
译者注:有向图是有方向的,即规定了 a→b 你就不能从 b→a 。
示例 1:
输入:graph = [[1,2],[3],[3],[]] 输出:[[0,1,3],[0,2,3]] 解释:有两条路径 0 -> 1 -> 3 和 0 -> 2 -> 3
示例 2:
输入:graph = [[4,3,1],[3,2,4],[3],[4],[]] 输出:[[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]
示例 3:
输入:graph = [[1],[]] 输出:[[0,1]]
示例 4:
输入:graph = [[1,2,3],[2],[3],[]] 输出:[[0,1,2,3],[0,2,3],[0,3]]
示例 5:
输入:graph = [[1,3],[2],[3],[]] 输出:[[0,1,2,3],[0,3]]
提示:
n == graph.length
2 <= n <= 15
0 <= graph[i][j] < n
graph[i][j] != i
(即,不存在自环)graph[i]
中的所有元素 互不相同- 保证输入为 有向无环图(DAG)
题解
8月25日每日一题
有向,无环这两个输入参数的特性使得这题的难度直线下降,不用考虑访问到已访问过的节点,不要考虑进入环的可能性
直接就根据入参重新构建一个反向的关系图,如,
原本入参告诉了从0节点可以前往4,3,1节点,而新的图上0的位置记录的是可以到达0节点的上一个节点有哪些,0节点是初始出发节点,显然没有,不如换个终点4节点。
可知,能到达4节点的上一个节点可能为【0,1,3】,0节点为初始节点,可以结束,1节点的上一个节点可能为【0】结束,3节点的上一个节点可能为【0,2】,2节点的上一个节点可能为【1】,1节点的上一个节点可能为【0】结束。
class Solution {
boolean[][] pathMap;
List<List<Integer>> list;
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
int target = graph.length-1;
list = new ArrayList<>();
createMap(graph);
List<Integer> ls = new ArrayList<>();
ls.add(target);
dfs(ls,target);
return list;
}
public void dfs(List<Integer> visitList, int node){
if (node == 0){
list.add(new ArrayList<>(visitList));
return;
}
if (pathMap[node].length > 0){
for (int i = 0; i < pathMap[node].length; i++) {
if (!pathMap[node][i])continue;
visitList.add(0,i);
dfs(visitList,i);
visitList.remove(0);
}
}
}
public void createMap(int[][] graph){
pathMap = new boolean[graph.length][graph.length];
for (int i = 0; i < graph.length; i++) {
for (int j = 0; j < graph[i].length; j++) {
pathMap[graph[i][j]][i] = true;
}
}
}
}
后续
从上面的例子可以看到第一开始从4节点找到1节点,1节点的上一个节点可能为【0】结束,而2节点后来又找到了1节点,这边可以优化下,额外记录下能到达0节点的所有点的可能路径,假设一个完整的能到达0路径是【8,6,5,1,0】
那么需要记录下 8经过【6,5,1,0】,6经过【5,1,0】,5经过【1,0】能到达0节点。
这样在后面再次絮叨6、5、1这些节点的时候无需再次尝试计算能否到达0节点
补充,大意了,直接从0节点开始搜索也是可以的,之所以想要反向搜索是想要从基础数据的层面来规避最后进入死胡同的情况,比如这样的情况
【【1,2】,【】,【】】最终结果应当是到达2节点,但是0节点也可以到达1节点,1节点最后却不能达到2节点,构建反向的路径的时候可以直接规避掉从0节点开始搜索进入1节点的情况
发表评论