给定一个有 n
个节点的有向无环图,用二维数组 graph
表示,请找到所有从 0
到 n-1
的路径并输出(不要求按顺序)。
graph
的第 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
保证输入为有向无环图 (GAD)
注意:本题与主站 797 题相同:<https://leetcode-cn.com/problems/all-paths-from-source-to- target/>
方法一:深度优先搜索 思路和算法
我们可以使用深度优先搜索的方式求出所有可能的路径。具体地,我们从 0 号点出发,使用栈记录路径上的点。每次我们遍历到点 n-1,就将栈中记录的路径加入到答案中。
特别地,因为本题中的图为有向无环图(DAG),搜索过程中不会反复遍历同一个点,因此我们无需判断当前点是否遍历过。
代码
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : vector<vector<int >> ans; vector<int > stk; void dfs (vector<vector<int >>& graph, int x, int n) { if (x == n) { ans.push_back (stk); return ; } for (auto & y : graph[x]) { stk.push_back (y); dfs (graph, y, n); stk.pop_back (); } } vector<vector<int >> allPathsSourceTarget (vector<vector<int >>& graph) { stk.push_back (0 ); dfs (graph, 0 , graph.size () - 1 ); return ans; } };
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { List<List<Integer>> ans = new ArrayList <List<Integer>>(); Deque<Integer> stack = new ArrayDeque <Integer>(); public List<List<Integer>> allPathsSourceTarget (int [][] graph) { stack.offerLast(0 ); dfs(graph, 0 , graph.length - 1 ); return ans; } public void dfs (int [][] graph, int x, int n) { if (x == n) { ans.add(new ArrayList <Integer>(stack)); return ; } for (int y : graph[x]) { stack.offerLast(y); dfs(graph, y, n); stack.pollLast(); } } }
[sol1-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution : def allPathsSourceTarget (self, graph: List [List [int ]] ) -> List [List [int ]]: ans = list () stk = list () def dfs (x: int ): if x == len (graph) - 1 : ans.append(stk[:]) return for y in graph[x]: stk.append(y) dfs(y) stk.pop() stk.append(0 ) dfs(0 ) return ans
[sol1-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int ** ans;int stk[15 ];int stkSize;void dfs (int x, int n, int ** graph, int * graphColSize, int * returnSize, int ** returnColumnSizes) { if (x == n) { int * tmp = malloc (sizeof (int ) * stkSize); memcpy (tmp, stk, sizeof (int ) * stkSize); ans[*returnSize] = tmp; (*returnColumnSizes)[(*returnSize)++] = stkSize; return ; } for (int i = 0 ; i < graphColSize[x]; i++) { int y = graph[x][i]; stk[stkSize++] = y; dfs(y, n, graph, graphColSize, returnSize, returnColumnSizes); stkSize--; } } int ** allPathsSourceTarget (int ** graph, int graphSize, int * graphColSize, int * returnSize, int ** returnColumnSizes) { stkSize = 0 ; stk[stkSize++] = 0 ; ans = malloc (sizeof (int *) * 16384 ); *returnSize = 0 ; *returnColumnSizes = malloc (sizeof (int ) * 16384 ); dfs(0 , graphSize - 1 , graph, graphColSize, returnSize, returnColumnSizes); return ans; }
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func allPathsSourceTarget (graph [][]int ) (ans [][]int ) { stk := []int {0 } var dfs func (int ) dfs = func (x int ) { if x == len (graph)-1 { ans = append (ans, append ([]int (nil ), stk...)) return } for _, y := range graph[x] { stk = append (stk, y) dfs(y) stk = stk[:len (stk)-1 ] } } dfs(0 ) return }
[sol1-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var allPathsSourceTarget = function (graph ) { const stack = [], ans = []; const dfs = (graph, x, n ) => { if (x === n) { ans.push (stack.slice ()); return ; } for (const y of graph[x]) { stack.push (y); dfs (graph, y, n); stack.pop (); } } stack.push (0 ); dfs (graph, 0 , graph.length - 1 ); return ans; };
复杂度分析