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

news2025/2/26 22:16:47

3.所有可能路径

  • 题目描述

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

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

示例 1:

img

输入:graph = [[1,2],[3],[3],[]]
输出:[[0,1,3],[0,2,3]]
解释:有两条路径 0 -> 1 -> 30 -> 2 -> 3
  • 题目分析

image-20240314201033773

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

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

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数组?

这是因为在深度优先搜索中,我们使用了路径 path 来记录当前的访问状态,每次递归调用都会将当前节点加入路径,并在递归结束后将其移出路径。这样就不需要额外的 used 数组来标记节点是否被访问过,因为路径 path 本身已经隐式地记录了节点的访问状态。
当我们尝试访问一个节点时,首先会检查该节点是否已经在当前路径中,如果在,则说明形成了环路,不再继续访问;如果不在,则将该节点加入路径,并继续向下递归。在每一次递归结束后,我们会将最后一个节点从路径中移出,这样就能够正确地模拟节点的访问状态,而不需要额外的 used 数组来记录。
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(); // 回溯,移除当前节点,继续搜索其他邻居
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1528644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TypeScript(六)条件类型,函数,装饰器

条件类型 TypeScript 中的条件类型是一种高级类型&#xff0c;它使我们根据不同的条件创建更复杂的类型。 TS中的条件类型就是在类型中添加条件分支&#xff0c;以支持更加灵活的泛型 条件类型允许我们根据某个类型的属性是否满足某个条件&#xff0c;来确定最终的类型。 type…

【海贼王的数据航海】排序——冒泡|快速|归并排序|总结

目录 1 -> 交换排序 1.1 -> 冒泡排序 1.1.1 -> 代码实现 1.2 -> 快速排序 1.2.1 -> hoare版本 1.2.2 -> 挖坑法 1.2.3 -> 前后指针法 1.2.4 -> 快速排序(递归版) 1.2.5 -> 快速排序(非递归版) 2 -> 归并排序 2.1 -> 归并排序 2.…

泛微 OA - 根据流程 requestid 获取流程中的附件

泛微 OA - 根据流程 requestid 获取流程中的附件 在泛微 OA 流程中&#xff0c;附件是通过加密上传的&#xff0c;如果在第三方系统想要调用 OA 系统获取 OA 附件&#xff0c;暂时没有很好的方法实现。但是可以在本地进行调用&#xff0c;得到附件 url 地址、附件 id、附件上传…

蓝桥杯练习02随机数生成器

随机数生成器 介绍 实际工作中随机数的使用特别多&#xff0c;比如随机抽奖、随机翻牌。通过随机数还能实现很多有趣的效果&#xff0c;比如随机改变元素的位置或颜色。 本题需要在已提供的基础项目中使用JS知识封装一个函数&#xff0c;该函数可以根据需要&#xff0c;生成指…

01. 【Android教程】系统背景及结构概述

1. Android 的历史 Android 一词的本意指“人形机器人”&#xff0c;安迪•鲁宾 (Andy Rubin) 在 2003 年以此名创办了 Android 公司并开始召集团队研发 Android 系统。后于 2005 年被 Google 收购&#xff0c;安迪•鲁宾随后任 Google 工程部副总裁&#xff0c;继续负责 Andr…

数据可信流通:从运维信任到技术信任

1.数据可信流通概念 "数据可信流通"通常指的是确保数据在不同系统、应用程序或者组织之间的传输和交换过程中的可信性、完整性和安全性。在数据流通的过程中&#xff0c;确保数据的真实性、完整性和保密性是非常重要的&#xff0c;尤其是涉及到敏感信息或者重要数据…

大数据开发--01.初步认识了解

一.环境准备 1.使用虚拟机构建至少三台linux服务器 2.使用公有云来部署服务器 二.大数据相关概念 大数据是指处理和分析大规模数据集的一系列技术、工具和方法。这些数据集通常涉及海量的数据&#xff0c;包括结构化数据&#xff08;如关系型数据库中的表格&#xff09;以及…

Verdaccio部署及基础使用

1. Verdaccio 简介 Verdaccio&#xff0c;是一个轻量级的 npm 私有仓库的开源解决方案。npm是一个基于http的协议&#xff0c;用来存放软件包并且维护版本和依赖&#xff0c;利用 http 提供的 url路径 来对软件包进行增删改查。所以 Verdaccio 这款软件的核心就是实现 npm协议…

机器人路径规划:基于双向A*算法(bidirectional a star)的机器人路径规划(提供Python代码)

一、双向A*算法简介 传统A*算法是一种静态路网中求解最短路径最有效的方法&#xff0c; 它结合了BFS 算法和迪杰斯特拉算法(Dijkstra)的优点。 和迪杰斯特拉算法(Dijkstra)一样&#xff0c; A*算法能够用于 搜索最短路径&#xff1b; 和BFS 算法一样&#xff0c; A*算法可以用…

从头手搓一台ros2复合机器人(带机械臂)

一.前言 大家好呀&#xff0c;从本小节开始我们就步入了仿真篇&#xff0c;主要对机器人仿真进行介绍与操作&#xff0c;当然仿真有优点也有缺陷&#xff0c;基于对此学习&#xff0c;我们可以对上几小节创建的小车模型模拟硬件的特性&#xff0c; 比如&#xff1a; 有多重…

打开磁盘清理工具的9种方法,总有一种适合你

前言 你可以在Windows 10和11上使用许多第三方磁盘清理工具来进行清理。但是,别忘了Windows包含自己的磁盘清理工具,你可以使用该工具释放硬盘存储空间。一些第三方替代方案可能有更广泛的清理选项和功能,但磁盘清理仍然是消除多余文件的完美工具。 每个用户都应该不时地进…

vue 部署 abap BSP

How to Create a Vue.Js App with VS Code and Deploy... - SAP Community 详情见上面这个教程连接 Open VS Code and open a terminal window and run npm install -g vue/cli restart vscode. Open a terminal window again and go to your workspace folder to create the…

使用echart绘制拓扑图,树类型,自定义tooltip和label样式,可收缩

效果如图&#xff1a; 鼠标移上显示 vue3 - ts文件 “echarts”: “^5.4.3”, import { EChartsOption } from echarts import * as echarts from echarts/core import { TooltipComponent } from echarts/components import { TreeChart } from echarts/charts import { C…

VR历史建筑漫游介绍|虚拟现实体验店|VR设备购买

VR历史建筑漫游是一种利用虚拟现实技术&#xff0c;让用户可以身临其境地参观和探索历史建筑的体验。通过VR头显和相关设备&#xff0c;用户可以在虚拟环境中自由移动和互动&#xff0c;感受历史建筑的真实氛围和文化内涵。 在VR历史建筑漫游中&#xff0c;您可以选择不同的历史…

拿捏指针(三)

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱博客 所属栏目&#xff1a;C语言 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 前言 在这之前我们学习了《拿捏指针&#xff08;一&#xff09;》&#xff0c;《拿…

Centos7部署使用TELEMAC-MASCARET

Background TELEMAC-MASCARET是一款研究水动力学和水文学领域的高性能数值仿真开源软件。MASCARET&#xff08;1980&#xff09;和 TELEMAC&#xff08;1987&#xff09;最初是由法电集团所属的法国国立水利与环境实验室开发&#xff0c;随后整合为TELEMAC-MASCARET并由法英德三…

后端系统开发之——创建注册接口

原文地址&#xff1a;后端系统开发之——创建注册接口 - Pleasure的博客 下面是正文内容&#xff1a; 前言 这是一篇SpringBoot项目的实践篇。 主要用于介绍如何从零开始搭建某一种类型的系统。 个人认为&#xff0c;只要后端逻辑完善了&#xff0c;纵使前端页面千变万化都可…

【DL经典回顾】激活函数大汇总(二十四)(Absolute附代码和详细公式)

激活函数大汇总&#xff08;二十四&#xff09;&#xff08;Absolute附代码和详细公式&#xff09; 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里&#xff0c;激活函数扮演着不可或缺的…

个人开发者上架App流程

摘要 个人开发者完全可以将自己开发的App上传至应用商店进行上架。本文将介绍上架流程的通用步骤&#xff0c;包括确定App功能和定位、准备相关资料、开发App、提交审核、发布App和宣传推广等内容。 引言 个人开发者在如今的移动应用市场中也有机会将自己的作品推向更广泛的…

【书生·浦语大模型实战营】学习笔记3

文章目录 1. 大模型开发范式2. LangChain简介3. 构建向量数据库4. 搭建知识库助手5. Web Demo部署6. 动手实战环节环境配置知识库搭建InternLM接入LangChain构建检索问答链部署Web Demo 参考资料 1. 大模型开发范式 LLM局限性&#xff1a; 知识时效性&#xff1a;LLM无法获取最…