算法日记day 18(二叉树的所有路径|左叶子之和)

news2024/9/22 7:30:41

一、二叉树的所有路径

题目:

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

 示例 1:

输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

示例 2:

输入:root = [1]
输出:["1"]

思路:

采用前序遍历,递归和回溯法相辅相成, 用一个列表负责记录所走的路径,从根节点开始对每个节点依次遍历,直到遇到左右子节点均为空为止(即叶子节点),结束遍历,同时记录该条路径上所有的节点,并用"->"拼接

代码:

public void traversal(TreeNode root, List<Integer> paths, List<String> res) {
    paths.add(root.val); // 将当前节点的值添加到路径列表中

    // 如果当前节点是叶子节点,将路径列表转换为字符串并加入结果列表
    if (root.left == null && root.right == null) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < paths.size() - 1; i++) {
            sb.append(paths.get(i)).append("->");
        }
        sb.append(paths.get(paths.size() - 1));
        res.add(sb.toString());
        return;
    }

    // 递归处理左子树
    if (root.left != null) {
        traversal(root.left, paths, res);
        paths.remove(paths.size() - 1); // 回溯,移除左子树的路径节点
    }

    // 递归处理右子树
    if (root.right != null) {
        traversal(root.right, paths, res);
        paths.remove(paths.size() - 1); // 回溯,移除右子树的路径节点
    }
}
  • 功能:递归地遍历二叉树,并在叶子节点处将路径转换为字符串后存入结果列表。
  • 逻辑
    • 将当前节点的值 root.val 添加到路径列表 paths 中。
    • 如果当前节点是叶子节点(即左右子节点都为 null),将路径列表中的节点值按路径格式拼接为字符串,并添加到结果列表 res 中。
    • 递归处理左子树和右子树,同时在递归完成后进行回溯,即移除路径列表 paths 的最后一个节点,以便处理下一个分支的路径。
public List<String> binaryTreePaths(TreeNode root) {
    List<String> res = new ArrayList<>();
    List<Integer> paths = new ArrayList<>();
    if (root == null) {
        return res;
    }
    traversal(root, paths, res);
    return res;
}
  • 功能:初始化结果列表 res 和路径列表 paths,然后调用 traversal 方法进行遍历。
  • 逻辑
    • 如果 root 为 null,直接返回空的结果列表 res
    • 否则,调用 traversal 方法进行遍历,将结果存入 res 中。

二、左叶子之和

题目:

给定二叉树的根节点 root ,返回所有左叶子之和。

示例 1:

输入: root = [3,9,20,null,null,15,7] 
输出: 24 
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

示例 2:

输入: root = [1]
输出: 0

思路:

由于在遍历到叶子节点时并不清楚其是否为左叶子节点,因此在遍历时需要判断其父节点,如果其父节点有左子节点,且该左子节点是叶子节点,则将该左子节点的值加入最终结果,然后继续遍历下一个节点

代码:

//递归法
public int sumOfLeftLeaves(TreeNode root) {
    if (root == null) {
        return 0;
    }
    // 递归计算左子树中左叶子节点的和
    int leftNum = sumOfLeftLeaves(root.left);
    // 递归计算右子树中左叶子节点的和
    int rightNum = sumOfLeftLeaves(root.right);
    
    int count = 0;
    // 如果当前节点的左孩子存在,并且左孩子是叶子节点(即没有左右孩子)
    if (root.left != null && root.left.left == null && root.left.right == null) {
        count = root.left.val;  // 将左叶子节点的值加入到计数中
    }
    
    // 返回当前子树中左叶子节点值之和
    return leftNum + rightNum + count;
}
  1. 递归基础情况

    • 如果 root 为 null,即空节点,则直接返回 0,表示没有左叶子节点。
  2. 递归计算

    • leftNum 表示递归计算左子树中左叶子节点值之和。
    • rightNum 表示递归计算右子树中左叶子节点值之和。
  3. 判断左叶子节点

    • 在当前节点 root 的左孩子存在,并且左孩子的左右孩子都为 null,即左孩子是叶子节点。
    • 如果满足条件,将左孩子节点的值 root.left.val 加入到 count 中。
  4. 返回结果

    • 返回当前子树中所有左叶子节点的值之和,即 leftNum + rightNum + count
//迭代法
public int sumOfLeftLeaves(TreeNode root) {
    if (root == null) return 0;
    
    Stack<TreeNode> stack = new Stack<> ();
    stack.add(root);  // 将根节点压入栈
    
    int result = 0;
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();  // 弹出栈顶节点
        
        // 如果当前节点的左孩子存在,并且左孩子是叶子节点(即没有左右孩子)
        if (node.left != null && node.left.left == null && node.left.right == null) {
            result += node.left.val;  // 将左叶子节点的值加入到结果中
        }
        
        // 先压入右孩子,再压入左孩子,保证左孩子先被处理(因为栈是先入后出)
        if (node.right != null) {
            stack.add(node.right);
        }
        if (node.left != null) {
            stack.add(node.left);
        }
    }
    
    return result;
}
  1. 初始处理

    • 如果 root 为 null,直接返回 0
  2. 使用栈迭代

    • 创建一个 Stack<TreeNode> 类型的栈,并将根节点 root 压入栈中。
  3. 迭代过程

    • 在循环中,弹出栈顶的节点 node
    • 如果 node 的左孩子存在,并且是叶子节点(即左右孩子都为 null),则将左孩子节点的值加入到 result 中。
  4. 节点处理顺序

    • 因为栈是后进先出的数据结构,所以先将右孩子压入栈,再将左孩子压入栈,这样可以保证在处理时左孩子先被处理。
  5. 返回结果

    • 循环结束后,返回 result,即为二叉树中所有左叶子节点值之和。

今天的学习就到这里

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

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

相关文章

福州高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

随着制造业的转型升级&#xff0c;智能制造已成为行业发展的重要趋势。福州高校大学智能制造实验室作为该领域的重要研究基地&#xff0c;积极响应国家发展战略&#xff0c;不断探索和创新智能制造技术。数字孪生技术作为智能制造领域的前沿技术&#xff0c;通过将物理世界的实…

基于ansible进行运维自动化的研究以及相关的属性

一、ansible-简介 介绍 ansible是新出现的自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c; 实现了批量系统配置、批量程序部署、批量运行命令等功能。 无客户端。 …

基于区块链技术的中药饮片代煎配送服务与监管平台

业务背景 近年来&#xff0c;随着公众对中医药青睐有加&#xff0c;中药代煎服务作为中医药现代化的重要一环&#xff0c;在全国各地蓬勃兴起。鉴于传统煎煮方式的繁琐耗时&#xff0c;医疗机构纷纷转向与第三方中药饮片企业合作&#xff0c;采用集中代煎模式。这些第三方煎药中…

【数据结构】链表(单链表实现 + 详解 + 原码)

&#x1f387;&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳&#xff0c;欢迎大佬指点&#xff01; 人生格言: 当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友…

uni-app AppStore Connect上传拒绝汇总

1.Guideline 2.3.3 - Performance - Accurate Metadata 问题是图片不对&#xff0c;最好是自己截图&#xff0c;然后用香蕉云编 上传图片合成图片 2.Guideline 5.1.2 - Legal - Privacy - Data Use and Sharing 解决办法&#xff1a;在uniapp manifest.json找到 APP常用其他…

LabVIEW汽车动态信号模拟系统

随着汽车工业的快速发展&#xff0c;对汽车电子控制单元&#xff08;ECU&#xff09;的测试与仿真需求日益增加。开发了一种基于LabVIEW软件开发的汽车动态信号模拟系统&#xff0c;该系统能有效模拟ECU在实车环境下的工作状态&#xff0c;为ECU的开发和测试提供了一个高效、经…

react中如何mock数据

1.需求说明 因为前后端分离开发项目&#xff0c;就会存在前端静态页面写好了&#xff0c;后端数据接口还没写好&#xff1b;这时候前端就需要自己定义数据来使用。 定义数据有三种方式&#xff1a;直接写死数据、使用mock软件、json-server工具 这里讲解通过json-server工具…

C# 匿名函数与Lambda表达式

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 1.匿名函数 在 C# 中&#xff0c;匿名函数是一种没有名称的函数&#xff0c;可以直接在代码中定义和使用 匿名函数主要有两种形式&#xff1a;匿名方法和Lambda 表…

Jetpack Compose多页面跳转示例

示例&#xff1a; 使用Jetpack Compose开发android,实现功能&#xff1a;第1个界面有一个文本输入框输入消费金额&#xff0c;下面有个确定按钮&#xff0c;点击确定按钮后跳转到第2个界面&#xff0c;显示你的消费金额是XX,这个金额来自第1个界面的输入。 实操 使用 Jetpack …

C语言实现顺序结构二叉树-堆

文章目录 &#x1f3af;引言&#x1f453;C语言实现顺序结构二叉树-堆1.树的概念与结构1.1概念与结构1.2树的相关术语 2.二叉树2.1概念与结构2.2特殊的二叉树2.2.1满二叉树2.2.2完全二叉树 3.二叉树的存储结构3.1顺序存储3.2链式存储 4.堆的实现4.1堆的概念与结构4.2向上调增算…

AI+HPC 部署优化面试范围分享

背景 最近几年生成式AI技术和自动驾驶技术发展发展很快&#xff0c;这些行业对于算法的运行效率有很高的要求&#xff0c;尤其一个模型在训练完成后运行到设备上&#xff0c;需要大量的工作&#xff0c;包括模型的剪枝、蒸馏、压缩、量化、算子优化、系统优化等。 对于传统的…

浏览器的最大并发数(http1.1)

HTTP/1.1&#xff1a;每个资源请求通常需要单独的TCP连接&#xff0c;尽管支持Keep-Alive机制&#xff0c;允许在同一个TCP连接上连续发送多个请求。但通常浏览器限制并发TCP连接数&#xff08;例如&#xff0c;每个域名最多6个并发连接&#xff09;。 HTTP/2&#xff1a;引入…

C++:函数对象和函数调用运算符(函数、函数指针、lambda函数对象、bind创建的对象、重载了函数调用符的类对象)

函数对象和函数调用运算符 A.What&#xff08;函数对象&#xff09; 如果类定义了函数调用运算符&#xff0c;则该类的对象称为函数对象 其中重载的运算符operator()被称为函数调用运算符 B.Which&#xff08;有哪些可调用函数对象&#xff09; 函数&#xff1a;一般函数&…

UE4-打包游戏,游戏模式,默认关卡

一.打包游戏 注意windows系统无法打包苹果系统的执行包&#xff0c;只能使用苹果系统打包。 打包完之后是一个.exe文件。 打包要点&#xff1a; 1.确定好要操控的角色和生成位置。 2.设置默认加载的关卡和游戏模式。 在这个界面可以配置游戏的默认地图和游戏的模式&#xff0c;…

springboot+webSocket对接chatgpt

webSocket对接参考 话不多说直接上代码 WebSocket package com.student.config;import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springfram…

C#知识|账号管理系统:实现修改管理员登录密码

哈喽,你好啊,我是雷工! 本节主要记录实现修改管理员登录密码的后端逻辑及相关功能,以下为学习笔记。 01 实现逻辑 ①:首先输入原密码,验证,验证通过然后可以输入新密码进行修改; ②:新密码修改为了避免输入失误导致输入的密码与自己以为修改的密码不符的情况,增加了…

Langchain核心模块与实战[7]:专业级Prompt工程调教LLM[输入输出接口、提示词模板与例子选择器的协同工程]

Langchain核心模块与实战[7]:专业级Prompt工程调教LLM[输入输出接口、提示词模板与例子选择器的协同工程] 1. 大模型IO接口 任何语言模型应用的核心元素是…模型的输入和输出。LangChain提供了与任何语言模型进行接口交互的基本组件。 提示 prompts : 将模型输入模板化、动态…

**卷积神经网络典型CNN**

LeNet&#xff1a;最早用于数字识别的CNN AlexNet&#xff1a;2012年ILSVRC比赛冠军&#xff0c;远超第二名的CNN&#xff0c;比LeNet更深&#xff0c;用多层小卷积叠加来替换单个的大卷积 ZF Net&#xff1a;2013ILSVRC冠军 GoogleNet&#xff1a;2014ILSVRC冠军 VGGNet&a…

go语言Gin框架的学习路线(十一)

目录 GORM的CRUD教程 更新操作 更新所有字段 更新指定字段 使用 Select 和 Omit 更新 无 Hooks 更新 批量更新 删除操作 删除记录 批量删除 软删除 物理删除 示例代码 GORM的CRUD教程 CRUD 是 "Create, Read, Update, Delete"&#xff08;创建、查询、…

百度,有道,谷歌翻译API

API翻译 百度&#xff0c;有道&#xff0c;谷歌API翻译&#xff08;只针对中英相互翻译&#xff09;,其他语言翻译需要对应from&#xff0c;to的code 百度翻译 package fills.tools.translate; import java.util.ArrayList; import java.util.HashMap; import java.util.Lis…