回溯题目:所有可能的路径

题目

标题和出处

标题:所有可能的路径

出处:797. 所有可能的路径

难度

4 级

题目描述

要求

给定一个有 n \texttt{n} n 个结点的有向无环图,结点从 0 \texttt{0} 0 n − 1 \texttt{n} - \texttt{1} n1 编号,找出所有从结点 0 \texttt{0} 0 到结点 n − 1 \texttt{n} - \texttt{1} n1 的路径,按任意顺序返回答案。

图的表示如下: graph[i] \texttt{graph[i]} graph[i] 是从结点 i \texttt{i} i 可以访问的所有结点的列表(即从结点 i \texttt{i} i 到结点 graph[i][j] \texttt{graph[i][j]} graph[i][j] 存在一条有向边)。

示例

示例 1:

示例 1

输入: graph   =   [[1,2],[3],[3],[]] \texttt{graph = [[1,2],[3],[3],[]]} graph = [[1,2],[3],[3],[]]
输出: [[0,1,3],[0,2,3]] \texttt{[[0,1,3],[0,2,3]]} [[0,1,3],[0,2,3]]
解释:有两条路径: 0 → 1 → 3 \texttt{0} \rightarrow \texttt{1} \rightarrow \texttt{3} 013 0 → 2 → 3 \texttt{0} \rightarrow \texttt{2} \rightarrow \texttt{3} 023

示例 2:

示例 2

输入: graph   =   [[4,3,1],[3,2,4],[3],[4],[]] \texttt{graph = [[4,3,1],[3,2,4],[3],[4],[]]} 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]] \texttt{[[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]} [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]

数据范围

  • n = graph.length \texttt{n} = \texttt{graph.length} n=graph.length
  • 2 ≤ n ≤ 15 \texttt{2} \le \texttt{n} \le \texttt{15} 2n15
  • 0 ≤ graph[i][j] < n \texttt{0} \le \texttt{graph[i][j]} < \texttt{n} 0graph[i][j]<n
  • graph[i][j] ≠ i \texttt{graph[i][j]} \ne \texttt{i} graph[i][j]=i(即不存在自环)
  • graph[i] \texttt{graph[i]} graph[i] 中的所有元素各不相同
  • 保证输入为有向无环图

解法

思路和算法

这道题要求找到所有从结点 0 0 0 到结点 n − 1 n - 1 n1 的路径。由于给定的图是有向无环图,因此图中的任意一条路径都不会访问同一个结点两次,路径的长度一定是有限的。可以使用回溯得到所有路径。

从结点 0 0 0 出发。对于每个访问到的结点 node \textit{node} node,执行如下操作。

  1. node \textit{node} node 添加到路径的末尾。

  2. 判断 node \textit{node} node 是否等于 n − 1 n - 1 n1,执行相应的操作。

    • 如果 node = n − 1 \textit{node} = n - 1 node=n1,则找到一条从结点 0 0 0 到结点 n − 1 n - 1 n1 的路径,将路径添加到答案中。

    • 如果 node ≠ n − 1 \textit{node} \ne n - 1 node=n1,则对于 graph [ node ] \textit{graph}[\textit{node}] graph[node] 中的每个结点 next \textit{next} next,递归地访问 next \textit{next} next

  3. node \textit{node} node 从路径的末尾移除。

遍历结束时,即可得到所有从结点 0 0 0 到结点 n − 1 n - 1 n1 的路径。

代码

class Solution {
    List<List<Integer>> allPaths = new ArrayList<List<Integer>>();
    List<Integer> temp = new ArrayList<Integer>();
    int n;
    int[][] graph;

    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        this.n = graph.length;
        this.graph = graph;
        backtrack(0);
        return allPaths;
    }

    public void backtrack(int node) {
        temp.add(node);
        if (node == n - 1) {
            allPaths.add(new ArrayList<Integer>(temp));
        } else {
            int[] nextNodes = graph[node];
            for (int next : nextNodes) {
                backtrack(next);
            }
        }
        temp.remove(temp.size() - 1);
    }
}

复杂度分析

  • 时间复杂度: O ( n × 2 n ) O(n \times 2^n) O(n×2n),其中 n n n 是图中的结点数。路径数最多是 2 n 2^n 2n,对于每条路径需要 O ( n ) O(n) O(n) 的时间添加到答案中,因此时间复杂度是 O ( n × 2 n ) O(n \times 2^n) O(n×2n)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是图中的结点数。存储当前路径的列表和递归调用栈需要 O ( n ) O(n) O(n) 的空间。注意返回值不计入空间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的车尔尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值