Leetcode 二叉树中的最大路径和

在这里插入图片描述

算法思想

这道题要求在一棵二叉树中找到路径和最大的路径。路径可以从树中任意一个节点开始,到任意一个节点结束,但路径上的节点必须是连续的。

算法使用递归的方式来遍历树中的每个节点,并在遍历过程中计算包含当前节点的最大路径和。具体步骤如下:

  1. 递归辅助函数 (calculatePathSum)

    • 这个函数用于计算以当前节点为起点的最大路径和。
    • 它通过递归分别计算左右子树的最大路径和,然后加上当前节点的值来得到当前路径的和。
  2. 路径和的计算

    • leftMaxrightMax 分别表示左子树和右子树的最大路径和,但如果子树路径和为负数,则忽略该子树路径,即设为 0,因为负数会降低总路径和。
    • currentMaxPathSum 代表了经过当前节点的路径和,包含左子树路径、当前节点值、右子树路径之和。
  3. 全局最大路径和的更新

    • 每当计算出一个 currentMaxPathSum,就将其与当前的全局最大路径和 maxSum 比较,以确保 maxSum 始终保存最大值。
    • 这样就能保证即使最优路径不经过根节点,也能记录全局最大路径和。
  4. 返回值

    • 函数返回当前节点值加上左右子树中较大的那个路径和,这样在递归向上返回时,可以确保每个节点返回的路径是包含它自身和一边子树的最大路径和。

复杂度分析

  • 时间复杂度:(O(n)),其中 (n) 是树中的节点数,因为每个节点只访问一次。
  • 空间复杂度:(O(h)),其中 (h) 是树的高度,这是递归调用栈的最大深度。

代码的运行流程示例

假设输入的树结构如下:

    1/ \2   3
  • 从根节点 1 开始,递归计算其左右子树的最大路径和。
  • 对于节点 2 和节点 3,它们的左右子树均为 null,因此它们的左右路径和为 0
  • 计算出节点 2 的最大路径和为 2,节点 3 的最大路径和为 3
  • 根节点 1 的路径和为 1 + 2 + 3 = 6
  • 最终结果是 6
class Solution {private int maxSum = Integer.MIN_VALUE;public int maxPathSum(TreeNode root) {calculateSum(root);return maxSum;}private int calculateSum(TreeNode root) {if(root == null) return 0;int leftMax = Math.max(calculateSum(root.left), 0);int rightMax = Math.max(calculateSum(root.right), 0);int currentmaxSum = root.val + leftMax + rightMax;maxSum = Math.max(currentmaxSum, maxSum);return root.val + Math.max(leftMax, rightMax);}
}

为什么 calculateSum 返回的不是node.val + leftMax + rightMax;?

这行代码的设计是因为我们要分清两种不同的情况:

  1. 更新全局最大路径和

    • 我们在每个节点处计算经过该节点的完整路径和,这条路径是包含了左子树、当前节点和右子树的路径和,即 node.val + leftMax + rightMax。这就是我们在 maxSum = Math.max(maxSum, currentMaxPathSum); 这一步中更新的内容。
    • 这个路径和会用于更新全局最大路径和 maxSum,因为这可能是当前遇到的最大路径。
  2. 返回值的意义

    • 在递归中,返回值代表以当前节点为起点向上递归时的“可选最大路径和”。
    • 注意,递归返回时不能同时选择左右子树的路径,因为递归往上走只能选择一条单一路径,而不是一条完整的左-当前-右的路径。
    • 因此,返回 node.val + Math.max(leftMax, rightMax);,表示从当前节点向上递归时,所能带回的最大路径和只能选择左子树或右子树中的较大者,来形成一条单向的路径。

总结

如果直接返回 node.val + leftMax + rightMax,那么递归上层的节点就会以包含当前节点左右子树路径的方式继续扩展路径,造成逻辑上的错误,因为每条路径必须是从上往下的一条单路径。

所以:

  • 全局最大路径和:用 node.val + leftMax + rightMax 来更新,因为这条路径可以是左-当前-右的完整路径。
  • 递归返回值:用 node.val + Math.max(leftMax, rightMax),因为只能选择左右子树中的一个路径继续往上递归。

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

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

相关文章

计算机视觉实验一:图像基础处理

1. 图像的直方图均衡 1.1 实验目的与要求 (1)理解直方图均衡的原理与作用; (2)掌握统计图像直方图的方法; (3)掌握图像直方图均衡的方法。 1.2 实验原理及知识点 直方图均衡化是通过灰度变换将一幅图象转换为另一幅均衡直方图,即在每个灰度级上都具有相同的象素…

计算结构力学:多自由度振动系统

本文以笔记的形式记录计算结构力学的若干基础知识。 注1:限于研究水平,分析难免不当,欢迎批评指正。 注2:文章内容会不定期更新。 预修1:线性代数 1. 标准特征值 复矩阵Schur分解:对于复矩阵&#xff0c…

Linux基础环境搭建(CentOS7)- 安装Scala和Spark

#Linux基础环境搭建(CentOS7)- 安装Scala和Spark Linux基础环境搭建(CentOS7)- 安装Scala和Spark 大家注意以下的环境搭建版本号,如果版本不匹配有可能出现问题!(spark不要下2.4版本的 会报错…

Vue3使用AntV | X6绘制流程图:开箱即用

x6官方地址X6图编辑引擎 | AntV 官方文档仔细地介绍了很多丰富的功能,这里的demo可以满足基本的使用,具体拓展还需要仔细看文档内容 先上效果图 1、安装 通过 npm 或 yarn 命令安装 X6。 # npm npm install @antv/x6 --save# yarn yarn add @antv/x6 初始化画布 <di…

MCU内存结构解析:FLASH、ROM与RAM的功能与区别

目录 MCU内存概览 1. FLASH存储器 FLASH的特点与应用 2. ROM存储器 ROM的特点与应用 3. RAM存储器 RAM的特点与应用 MCU中FLASH、ROM与RAM的典型配置方式 总结 在嵌入式开发中&#xff0c;MCU&#xff08;微控制器&#xff09;是实现控制和数据处理的核心。MCU内部的存储结构对…

安装使用docker harbor并推送镜像到仓库

1.概要 通过上一章节的讲解&#xff0c;我们基本了解了docker的操作命令&#xff0c;在文章的最后我们成功的推送一个镜像到DockerHub的镜像仓库。从流程上说&#xff0c;操作过程可以说很完美&#xff0c;但是整个推送过程消耗的时间太长&#xff0c;我们消耗了大量时间在访问…

HTML练习题:彼岸的花(web)

展示效果: 代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>彼岸の花</title><style…

thinkphp和vue基于Workerman搭建Websocket服务实现用户实时聊天,完整前后端源码demo及数据表sql

最近接了一个陪玩小程序&#xff0c;其中有一个实时聊天的项目&#xff0c;需要搭建Websocke服务&#xff0c;通过多方考虑选择了通过GatewayWorker框架&#xff08;基于Workerman&#xff09;,将代码提取了出来&#xff0c;用到的框架封装到了vendor目录下&#xff0c;完整前后…

被上传文件于后端的命名策略

上一篇博客我们了解了前端上传的文件资源应该存放在后端项目中的什么位置&#xff0c;那么随之而来的另一个问题——我们应该如何为上传的文件命名呢&#xff1f;往往直接采用原文件名并不稳妥&#xff0c;会导致命名冲突、文件冲突、数据库管理冲突等多种问题&#xff0c;下面…

【计算机网络 - 基础问题】每日 3 题(五十八)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

C++ 二叉树进阶:相关习题解析

目录 1. 二叉树创建字符串。 2. 二叉树的分层遍历1 3. 二叉树的分层遍历2 4. 二叉树的最近公共祖先 5. 将二叉搜索树转换为排序的双向链表 6. 从前序与中序遍历序列构造二叉树 7. 从中序与后序遍历序列构造二叉树 8. 二叉树的前序遍历&#xff0c;非递归迭代实现 9.…

云舟观测:基于eBPF监控主机的TCP网络连接

1 背景 机器网络监控信息在日常问题排查中扮演着至关重要的角色&#xff0c;是不可或缺的工具。通过对网络流量的深入分析&#xff0c;我们不仅能有效评估网络性能&#xff0c;还能迅速识别异常行为&#xff0c;例如流量突然激增、未知的数据传输等&#xff0c;这些对于保障网络…

【IC每日一题】

IC每日一题 1&#xff1a;锁存器(latch)、触发器(flip-flop)、寄存器的概念及区别1.1 概念1.2 锁存器的危害1.3 如何避免产生锁存器 2 手撕题&#xff1a;边沿检测2.1 边沿检测(上升沿、下降沿、双边沿)2.1.1 波形图2.1.2 算法步骤2.1.3 代码 2.2 序列模三检测器2.2.1 描述2.2.…

使用 Docker Compose 将数据版 LobeChat 服务端部署

LobeChat 是一个基于 TypeScript 的开源聊天机器人项目&#xff0c;支持本地部署和接入多个大语言模型。本文介绍如何使用 Docker Compose 将 LobeChat 服务端及其数据库部署到生产环境&#xff0c;让您拥有一个私有化的、可定制的 AI 聊天助手。 一、部署前准备 服务器&…

驱动和芯片设计哪个难

驱动和芯片设计哪个难 芯片设计和驱动开发 芯片设计和驱动开发 都是具有挑战性的工作&#xff0c;它们各自有不同的难点和要求。 对于芯片设计&#xff0c;它是一个集高精尖于一体的复杂系统工程&#xff0c;涉及到从需求分析、前端设计、后端设计到流片的全过程。 芯片设计的…

DICOM标准:DICOM服务类详解,了解存储服务类、查询/检索服务类(Q/R Service Class)和工作流管理服务类等原理

目录 一、概述 二、存储服务类&#xff08;Storage Service Class&#xff09; 存储操作&#xff08;C-STORE&#xff09; 确认操作&#xff08;C-STORE-RSP&#xff09; 三、查询/检索服务类&#xff08;Query/Retrieve Service Class&#xff09; 查询操作&#xff08;C…

八,Linux基础环境搭建(CentOS7)- 安装Mysql和Hive

Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Mysql和Hive 大家注意以下的环境搭建版本号&#xff0c;如果版本不匹配有可能出现问题&#xff01; 一、Mysql下载及安装 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Orac…

【数据结构 | PTA】懂蛇语

懂蛇语 在《一年一度喜剧大赛》第二季中有一部作品叫《警察和我之蛇我其谁》&#xff0c;其中“毒蛇帮”内部用了一种加密语言&#xff0c;称为“蛇语”。蛇语的规则是&#xff0c;在说一句话 A 时&#xff0c;首先提取 A 的每个字的首字母&#xff0c;然后把整句话替换为另一…

Virtuoso使用layout绘制版图、使用Calibre验证DRC和LVS

1 绘制版图 1.1 进入Layout XL 绘制好Schmatic后&#xff0c;在原理图界面点击Launch&#xff0c;点击Layout XL进入版图绘制界面。 1.2 导入元件 1、在Layout XL界面左下角找到Generate All from Source。 2、在Generate Layout界面&#xff0c;选中“Instance”&#…

Spring事务的实现方式

前言 Spring的spring-tx模块提供了对事务管理支持&#xff0c;使用Spring事务可以让我们从复杂的事务处理中得到解脱&#xff0c;无需去处理获得连接、关闭连接、事务提交和回滚等这些操作。Spring事务管理是Spring框架提供的一个核心功能&#xff0c;它允许开发者以声明式或编…