加载中...
剑指 Offer II 110-所有路径
发表于:2021-12-03 | 分类: 中等
字数统计: 1.1k | 阅读时长: 5分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/bP4bmD

中文题目

给定一个有 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$,就将栈中记录的路径加入到答案中。

特别地,因为本题中的图为有向无环图($\text{DAG}$),搜索过程中不会反复遍历同一个点,因此我们无需判断当前点是否遍历过。

代码

[sol1-C++]
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]
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]
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]
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]
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]
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; };

复杂度分析

  • 时间复杂度:$O(n \times 2^n)$,其中 $n$ 为图中点的数量。我们可以找到一种最坏情况,即每一个点都可以去往编号比它大的点。此时路径数为 $O(2^n)$,且每条路径长度为 $O(n)$,因此总时间复杂度为 $O(n \times 2^n)$。

  • 空间复杂度:$O(n)$,其中 $n$ 为点的数量。主要为栈空间的开销。注意返回值不计入空间复杂度。

统计信息

通过次数 提交次数 AC比率
2628 3161 83.1%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
剑指 Offer II 109-开密码锁
下一篇:
剑指 Offer II 048-序列化与反序列化二叉树
本文目录
本文目录