news 2026/3/24 17:34:02

leetcode257二叉树的所有路径

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
leetcode257二叉树的所有路径

找出所有根节点到叶子结点的路径,这题比较容易想到的是回溯,不过层序遍历用两个队列也可以实现。这里还是只讲回溯

回溯版本一:

递归函数作用:处理传入结点的所有子孙结点,形成以其左右孩子为起点的到各叶子结点的路径。遍历到叶子结点时,组装当前这条路径结果

回溯状态:path集合

递归出口:遍历到叶子结点时,组装当前这条路径结果

第一步:根结点加入path

第二步:将根结点的左孩子结点加入path, 递归处理根结点的左孩子结点,处理完后,移除path中保存的根结点的左孩子结点,此时path中只有根结点

第三步:将根结点的右孩子结点加入path, 递归处理根结点的右孩子结点,处理完后,移除path中保存的根结点的右孩子结点,此时path中只有根结点

class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> res = new ArrayList<>(); //根结点为空,直接返回空集合 if (root == null) return res; //path用来装某条路径上的所有结点 List<Integer> path = new ArrayList<>(); //根结点的值先加入path path.add(root.val); //处理根结点的所有子孙结点,加到相应的路径结果中 dfs(root, path, res); // System.out.println(path); return res; } /** *递归函数作用:处理传入结点的所有子孙结点,形成以其左右孩子为起点的各种到叶子结点的路径。 *遍历到叶子结点时,组装当前这条路径结果 */ private void dfs(TreeNode node, List<Integer> path, List<String> res) { // 如果是叶子结点:把整条路径拼接成字符串 if (node.left == null && node.right == null) { res.add(joinPath(path)); return; } //如果存在左孩子结点 if (node.left != null) { //左孩子结点值加入path path.add(node.left.val); //递归处理左孩子的所有子孙结点 dfs(node.left, path, res); //将path中的左孩子结点值移除 path.remove(path.size() - 1); } //如果存在右孩子结点 if (node.right != null) { //右孩子结点值加入path path.add(node.right.val); //递归处理右孩子的所有子孙结点 dfs(node.right, path, res); //将path中的右孩子结点值移除 path.remove(path.size() - 1); } } //将path中的结点值拼接成想要的字符串 private String joinPath(List<Integer> path) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { if (i > 0) sb.append("->"); sb.append(path.get(i)); } return sb.toString(); } }

remove结点版:

class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> res = new ArrayList<>(); if (root == null) return res; List<TreeNode> path = new ArrayList<>(); path.add(root); dfs(root, path, res); return res; } private void dfs(TreeNode node, List<TreeNode> path, List<String> res) { //如果是叶子结点:把整条路径拼接成字符串 if (node.left == null && node.right == null) { res.add(joinPath(path)); } else { if (node.left != null) { path.add(node.left); dfs(node.left, path, res); path.remove(node.left); } if (node.right != null) { path.add(node.right); dfs(node.right, path, res); path.remove(node.right); } } } private String joinPath(List<TreeNode> path) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { if (i > 0) sb.append("->"); sb.append(Integer.toString(path.get(i).val)); } return sb.toString(); } }

回溯版本二:

递归函数作用:处理传入结点为根的二叉树所有结点,形成传入结点到各叶子结点的路径。遍历到叶子结点时,组装当前这条路径结果

回溯状态:path集合

递归出口:遍历到叶子结点时,组装当前这条路径结果

第一步:将根结点值加入path

第二步:递归处理根结点的左子树

第三步:递归处理根节点的右子树

最后:移除path中根节点值,此时,path为空

为什么最后要移除path中根节点值?

以上图中的左子树为例

左子树根结点的左右孩子处理完成的时候,path中有整颗二叉树的根结点值和其左子树的根结点值,接下来该处理整棵二叉树的右子树了,因此path中左子树的根结点值需要移除掉。

import java.util.*; class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> res = new ArrayList<>(); if (root == null) return res; List<Integer> path = new ArrayList<>(); dfs(root, path, res); return res; } private void dfs(TreeNode node, List<Integer> path, List<String> res) { // 1) 记录当前结点到路径 path.add(node.val); // 2) 如果是叶子结点:把整条路径拼接成字符串 if (node.left == null && node.right == null) { res.add(joinPath(path)); } else { if (node.left != null) dfs(node.left, path, res); if (node.right != null) dfs(node.right, path, res); } // 3) 回溯:撤销当前结点 path.remove(path.size() - 1); } private String joinPath(List<Integer> path) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { if (i > 0) sb.append("->"); sb.append(path.get(i)); } return sb.toString(); } }

remove结点版:

class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> res = new ArrayList<>(); if (root == null) return res; List<TreeNode> path = new ArrayList<>(); dfs(root, path, res); return res; } private void dfs(TreeNode node, List<TreeNode> path, List<String> res) { path.add(node); //如果是叶子结点:把整条路径拼接成字符串 if (node.left == null && node.right == null) { res.add(joinPath(path)); } else { if (node.left != null) { dfs(node.left, path, res); } if (node.right != null) { dfs(node.right, path, res); } } path.remove(node); } private String joinPath(List<TreeNode> path) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { if (i > 0) sb.append("->"); sb.append(Integer.toString(path.get(i).val)); } return sb.toString(); } }

回溯版本三:

这种方式虽然也是对的,但是不标准,推荐版本一和版本二,那种当前层代码移除当前层状态的方式!!!

import java.util.*; class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> res = new ArrayList<>(); if (root == null) return res; List<Integer> path = new ArrayList<>(); dfs(root, path, res); return res; } private void dfs(TreeNode node, List<Integer> path, List<String> res) { // 1) 记录当前结点到路径 path.add(node.val); // 2) 如果是叶子结点:把整条路径拼接成字符串 if (node.left == null && node.right == null) { res.add(joinPath(path)); } else { if (node.left != null) { dfs(node.left, path, res); //移除的是上面代码调用加入的node.left //属于父结点层移除左孩子 path.remove(path.size() - 1); } if (node.right != null){ dfs(node.right, path, res); //移除的是上面代码调用加入的node.right //属于父结点层移除右孩子 path.remove(path.size() - 1); } } } private String joinPath(List<Integer> path) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { if (i > 0) sb.append("->"); sb.append(path.get(i)); } return sb.toString(); } }

remove结点版:

class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> res = new ArrayList<>(); if (root == null) return res; List<TreeNode> path = new ArrayList<>(); dfs(root, path, res); return res; } private void dfs(TreeNode node, List<TreeNode> path, List<String> res) { path.add(node); //如果是叶子结点:把整条路径拼接成字符串 if (node.left == null && node.right == null) { res.add(joinPath(path)); } else { if (node.left != null) { dfs(node.left, path, res); path.remove(node.left); } if (node.right != null) { dfs(node.right, path, res); path.remove(node.right); } } } private String joinPath(List<TreeNode> path) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { if (i > 0) sb.append("->"); sb.append(Integer.toString(path.get(i).val)); } return sb.toString(); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/25 11:58:50

免费音频编辑器Audacity:3大核心功能让新手轻松上手

免费音频编辑器Audacity&#xff1a;3大核心功能让新手轻松上手 【免费下载链接】audacity Audio Editor 项目地址: https://gitcode.com/GitHub_Trending/au/audacity 还在为音频编辑软件的高昂费用和复杂操作而烦恼吗&#xff1f;今天为你介绍一款完全免费且功能强大…

作者头像 李华
网站建设 2026/3/25 7:50:23

群晖相册AI识别功能启用指南:无GPU设备也能体验智能相册

还在为DS918等设备无法使用群晖相册的人脸识别功能而烦恼吗&#xff1f;今天我将手把手教你如何通过开源补丁突破硬件限制&#xff0c;让无GPU设备也能拥有完整的AI相册体验。 【免费下载链接】Synology_Photos_Face_Patch Synology Photos Facial Recognition Patch 项目地址…

作者头像 李华
网站建设 2026/3/22 5:34:13

PyTorch-CUDA-v2.6镜像支持Kubernetes集群部署

PyTorch-CUDA-v2.6镜像支持Kubernetes集群部署 在AI模型训练日益复杂、算力需求持续攀升的今天&#xff0c;一个常见的场景是&#xff1a;算法工程师在本地用PyTorch跑通了代码&#xff0c;信心满满地提交到服务器&#xff0c;结果却报出CUDA not available或版本不兼容错误。…

作者头像 李华
网站建设 2026/3/15 10:47:27

UI-TARS:AI自动操控GUI界面的革命性突破

UI-TARS&#xff1a;AI自动操控GUI界面的革命性突破 【免费下载链接】UI-TARS-7B-SFT 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/UI-TARS-7B-SFT 导语&#xff1a;字节跳动最新发布的UI-TARS系列模型&#xff0c;通过单一视觉语言模型实现端到端GUI…

作者头像 李华
网站建设 2026/3/21 11:16:08

快速理解HDI技术优势:对比传统PCB工艺的五大升级

HDI技术凭什么成为高端电子产品的“隐形引擎”&#xff1f;你有没有想过&#xff0c;为什么现在的智能手机能做到越来越薄&#xff0c;性能却反而越来越强&#xff1f;一块不到手掌大的主板上&#xff0c;要塞进处理器、内存、射频模块、电源管理芯片……还要保证高速信号稳定传…

作者头像 李华
网站建设 2026/3/22 16:58:03

NSudo Windows系统权限管理工具完全指南:从新手到高手

NSudo Windows系统权限管理工具完全指南&#xff1a;从新手到高手 【免费下载链接】NSudo [Deprecated, work in progress alternative: https://github.com/M2Team/NanaRun] Series of System Administration Tools 项目地址: https://gitcode.com/gh_mirrors/nsu/NSudo …

作者头像 李华