原题链接: https://leetcode.com/problems/all-paths-from-source-to-target/
1. 题目介绍
Given a directed, acyclic graph of N nodes. Find all possible paths from node 0 to node N-1, and return them in any order.
The graph is given as follows: the nodes are 0, 1, …, graph.length - 1. graph[i] is a list of all nodes j for which the edge (i, j) exists.
给出一个有向无环图,图中共有 N 个节点。找出所有从零开始,到达 N-1 的路径。返回这些路径。可以把这些路径以任意顺序返回,但是路径内的节点顺序必须正确。
这个有向无环图如下:这些节点是0、1、······、graph.lenght-1 .
graph[ i ]中的值,是从 节点 i 出发,能到达的所有节点的标号。 如果 graph[ i ]为空,那就是没有下一个结点了。
Example:
Input: [[1,2], [3], [3], []]
Output: [[0,1,3],[0,2,3]]
Explanation: The graph looks like this:
0--->1
| |
v v
2--->3
There are two paths: 0 -> 1 -> 3 and 0 -> 2 -> 3.
Note:
The number of nodes in the graph will be in the range [2, 15].
You can print different paths in any order, but you should keep the order of nodes inside one path.
图中节点的个数范围是[2, 15].
可以把这些路径以任意顺序返回,但是路径内的节点顺序必须正确。
2. 解题思路-DFS递归求解
这道题是利用DFS + 递归解决的。需要说明的是,递归只是一种实现方式,和DFS、动态规划并不矛盾。很多题也可以使用动态规划 + 递归的组合方式解决(也就是记忆数组+递归)。
DFS 就是从一开始的节点出发,搜索每个节点能到达的所有点。
搜索某一个节点时,首先要把这个节点添加到路径里面去。如果这个点就是终点,那么就把那条路径记录下来,放到结果的Arraylist里面去;如果不是终点,那就继续搜这个点能去的其他点。 无论是否能到达终点,最终搜索完成后,一定要把这个节点从路径中删除。
实现代码
class Solution {
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
List<List<Integer>> ans = new ArrayList<>();
recursion( ans , 0, new ArrayList<Integer>() , graph);
return ans;
}
public void recursion(List<List<Integer>> ans , int curNode , List<Integer> path , int[][] graph ) {
path.add(curNode);
if( curNode == graph.length - 1) {
//如果是最后的节点,就放入path中
ans.add(new ArrayList<>(path));
/* 上面这一行代码不能是 ans.add(path);
* ans.add(path);是直接把path加进ans总结果中,
* ans.add(new ArrayList<>(path)); 则是把一个和path相同的ArrayList放进去,
* path本身并没有被放入ans。后面还要用同一个path去找其他的路径呢。
* 比如题目中给出来的例子,当找到0 1 3这一正确的路径后
* 后面找其他的路径时必然会改动path,如果path被放入ans,那么ans也被一起改了。
* 所以path要接着用,只需要放一个复制品到ans里面就行了
*/
}else {
//遍历这个节点所有可以到达的点
for(int i = 0 ; i < graph[curNode].length ; i++) {
recursion( ans , graph[curNode][i] , path , graph);
}
}
//每次递归结束都要从path中移去当前的节点。这一条语句和语句path.add(curNode)相对应
path.remove(path.size() - 1);
return;
}
}