描述

给定一个有 n 个节点的有向无环图,用二维数组 graph 表示,请找到所有从 0n-1 的路径并输出(不要求按顺序)。

graph 的第 i 个数组中的单元都表示有向图中 i 号节点所能到达的下一些结点(译者注:有向图是有方向的,即规定了 a→b 你就不能从 b→a ),若为空,就是没有下一个节点了。

示例

示例 1:
all_1.jpg

  1. 输入:graph = [[1,2],[3],[3],[]]
  2. 输出:[[0,1,3],[0,2,3]]
  3. 解释:有两条路径 0 -> 1 -> 3 0 -> 2 -> 3

示例 2:

all_2.jpg

输入: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]]

提示

  • n == graph.length
  • 2 <= n <= 15
  • 0 <= graph[i][j] < n
  • graph[i][j] != i
  • 保证输入为有向无环图 (GAD)

解题思路

1、 深度优先搜索

我们可以使用深度优先搜索的方式求出所有可能的路径。具体地,我们从 0 号点出发,使用栈记录路径上的点。每次我们遍历到点 n−1,就将栈中记录的路径加入到答案中。

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

代码

class Solution {
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    List<Integer> path = new ArrayList<Integer>();
    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        int n = graph.length;
        path.add(0);
        dfs(0, graph, path);
        return ans;
    }
    public void dfs(int index, int[][] graph, List<Integer> path) {
        if (index == graph.length - 1) {
            ans.add(new ArrayList<Integer>(path));
            return;
        }
        for (int num : graph[index]) {
            path.add(num);
            dfs(num, graph, path);
            path.remove(path.size() - 1);
        }
    }
}

2、 广度优先搜索

  • 需要定义一个带有路径的数据结构 Node, 这样才能保证当前节点的路径是从 0 开始到这个节点的路径。
  • 因为是有向无环图,所以不需要 visited 数组避免重复访问
  • 剩下的事情就是套用 BFS 模板

代码

class Solution {
    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        // bfs,从0开始一层一层向外搜索
        List<List<Integer>> resultList = new ArrayList<>();

        int n = graph.length;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(new Node(0));

        while (!queue.isEmpty()) {
            Node node = queue.poll();
            if (node.index == n - 1) {
                resultList.add(node.path);
                continue;
            }
            for (int next : graph[node.index]) {
                queue.offer(new Node(next, node.path));
            }
        }

        return resultList;
    }

    class Node {
        int index;
        List<Integer> path;

        Node(int index) {
            this.index = index;
            this.path = new ArrayList<>();
            // 把当前节点加入路径
            this.path.add(index);
        }

        Node(int index, List<Integer> path) {
            this.index = index;
            // 复制一个新的List
            this.path = new ArrayList<>(path);
            // 把当前节点加入路径
            this.path.add(index);
        }
    }
}