图论03-所有可能路径(Java)

3.所有可能路径

  • 题目描述

给你一个有 n 个节点的 有向无环图(DAG) ,请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特定顺序

graph[i] 是一个从节点 i 可以访问的所有节点的列表(即从节点 i 到节点 graph[i][j]存在一条有向边)。

示例 1:

java 复制代码
输入:graph = [[1,2],[3],[3],[]]
输出:[[0,1,3],[0,2,3]]
解释:有两条路径 0 -> 1 -> 3 和 0 -> 2 -> 3
  • 题目分析
java 复制代码
具体解题思路如下:
创建一个数组 used 用于标记节点是否被遍历过,初始化为0。
将源节点 0 加入初始路径,并调用 dfs 函数开始深度优先搜索。
在 dfs 函数中,首先判断当前节点是否为目标节点,如果是,则将当前路径添加到结果中,并标记当前节点未被访问过,然后返回。
如果当前节点不是目标节点,遍历当前节点可到达的所有节点,如果该节点未被访问过,则将节点加入当前路径,以该节点为起点继续递归调用 dfs 函数。在递归调用结束后,需要进行回溯操作,即移除最后一个节点,尝试其他路径。
这样就可以找出所有从源节点到目标节点的路径,并将其存储在 result 中。
  • Java代码分析

深度优先遍历(使用used数组)

java 复制代码
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;

public class Solution {
    // 用于存储当前路径的节点
    LinkedList<Integer> path = new LinkedList<>();
    // 存储所有符合条件的路径
    List<List<Integer>> result = new ArrayList<>();

    // 主函数,找出从源节点到目标节点的所有路径
    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        // 创建一个数组,用于标记节点是否被遍历
        int[] used = new int[graph.length];
        path.add(0); // 将源节点加入初始路径
        dfs(graph, used, 0); // 开始深度优先搜索
        return result; // 返回所有路径
    }

    // 深度优先搜索函数
    private void dfs(int[][] graph, int[] used, int startNode) {
        // 如果当前节点为目标节点,将当前路径添加到结果中
        if (startNode == graph.length - 1) {
            result.add(new ArrayList<>(path));
            used[startNode] = 0; // 标记当前节点未被访问
            return;
        }

        // 遍历当前节点可到达的所有节点
        for (int i = 0; i < graph[startNode].length; i++) {
            // 如果该节点未被访问过,继续深度优先搜索
            if (used[graph[startNode][i]] == 0) {
                path.add(graph[startNode][i]); // 将节点加入当前路径
                dfs(graph, used, graph[startNode][i]); // 以该节点为起点继续搜索
                path.removeLast(); // 回溯,移除最后一个节点,尝试其他路径
            }
        }
    }
}

为什么此题可以不使用used数组?

md 复制代码
这是因为在深度优先搜索中,我们使用了路径 path 来记录当前的访问状态,每次递归调用都会将当前节点加入路径,并在递归结束后将其移出路径。这样就不需要额外的 used 数组来标记节点是否被访问过,因为路径 path 本身已经隐式地记录了节点的访问状态。
当我们尝试访问一个节点时,首先会检查该节点是否已经在当前路径中,如果在,则说明形成了环路,不再继续访问;如果不在,则将该节点加入路径,并继续向下递归。在每一次递归结束后,我们会将最后一个节点从路径中移出,这样就能够正确地模拟节点的访问状态,而不需要额外的 used 数组来记录。
java 复制代码
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;

public class AllPathsSourceTarget {
    LinkedList<Integer> path = new LinkedList<>(); // 用于存储当前路径的节点序列
    List<List<Integer>> result = new ArrayList<>(); // 存储所有从起点到终点的路径

    // 主方法,返回所有从起点到终点的路径
    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        path.add(0); // 将起点添加到路径中
        dfs(graph, 0); // 开始深度优先搜索
        return result; // 返回所有路径结果
    }

    // 深度优先搜索方法
    private void dfs(int[][] graph, int x) {
        // 判断是否到达终点
        if (x == graph.length - 1) {
            result.add(new ArrayList<>(path)); // 将当前路径添加到结果中
            return;
        }

        // 遍历当前节点的邻居节点
        for (int i = 0; i < graph[x].length; i++) {
            int node = graph[x][i]; // 获取邻居节点
            path.add(node); // 将邻居节点加入路径中
            dfs(graph, node); // 递归搜索邻居节点
            path.removeLast(); // 回溯,移除当前节点,继续搜索其他邻居
        }
    }
}
相关推荐
汇匠源6 分钟前
零工市场小程序如何提高找兼职的效率?
java·大数据·开发语言·小程序·团队开发
一 乐11 分钟前
订餐点餐|订餐系统基于java的订餐点餐系统小程序设计与实现(源码+数据库+文档)
java·数据库·spring boot·后端·源码
蠢蠢的打码24 分钟前
8622 哈希查找
数据结构·c++·算法·链表·图论
dulu~dulu24 分钟前
数据冒险与控制冒险
java·开发语言·计算机组成原理
VX_CXsjNo127 分钟前
免费送源码:Java+B/S+ssm+MySQL 公众养老服务网上预订系统 计算机毕业设计原创定制
java·爬虫·mysql·eclipse·前端框架·课程设计·myeclipse
今天多喝热水1 小时前
Java工具--stream流
java
罗曼蒂克在消亡1 小时前
JDK——java.util.function
java·jdk
J不A秃V头A1 小时前
JSON字符串转换成Java集合对象
java·json
john_hjy2 小时前
7. 机器人项目
java·前端·javascript
那你为何对我三笑留情2 小时前
一、Spring Boot集成Spring Security之自动装配
java·spring boot·spring·spring security