LCR 110-所有可能的路径

Raphael Liu Lv10

给定一个有 n 个节点的有向无环图,用二维数组 graph 表示,请找到所有从 0n-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;
};

复杂度分析

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

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

 Comments
On this page
LCR 110-所有可能的路径