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.xdnf.cn/news/3747.html

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

相关文章

《2024中国城市音乐产业发展指数报告》重磅发布

11月4日,《2024中国城市音乐产业发展指数研究报告》(以下简称“报告”)在成都首次公开发布。该报告由中国音像与数字出版协会音乐产业促进工作委员会指导编制,道略产业研究院、四川音乐学院孙洪斌教授团队深度参与。 该指数评价对象涵盖直辖市、副省级城市和省会城市等共36个城…

解锁金融未来,Python带你玩转大数据!

厌倦了复杂的金融报表,想用数据驱动投资决策,却不知从何下手? 别担心! 《Python金融大数据分析快速入门与案例详解》带你轻松入门,掌握数据分析利器,成为金融领域的弄潮儿! 为什么选择这本书&…

STM32 + CubeMX + 硬件SPI + W5500 +TcpClient

这篇文章记录一下STM32W5500TCP_Client的调试过程,实现TCP客户端数据的接收与发送。 目录 一、W5500模块介绍二、Stm32CubeMx配置三、Keil代码编写1、添加W5500驱动代码到工程(添加方法不赘述,驱动代码可以在官网找)2、在工程中增…

template advanced

一.仿函数再探 stl_stack/queue-CSDN博客 在priority_queue中,我们介绍了仿函数作为第三个参数来改变堆的类型,而仿函数还有其他的用处。 那么我们是否可以借助优先级队列来对日期类进行排序呢? 答案是可以的,但前提是该日期…

spring源码[spring启动流程]

spring启动流程 AnnotationConfigApplicationContext的构造方法 1.父类构造方法,构造一个DefaultListableBeanFactory 在调用AnnotationConfigApplicationContext的构造方法之前,会调用父类GenericApplicationContext的无参构造方法,会构造…

使用Python做一个微信机器人

使用Python制作微信机器人是一个有趣且实用的项目,它可以让您自动化处理微信消息、监控微信群、甚至实现智能聊天等功能。 请求参数 Header 参数 export interface ApifoxModel {"X-GEWE-TOKEN": string;[property: string]: any; } Body 参数applicat…

Python-创建并调用自定义文件中的模块/函数

背景:在Python编程中,我们常常需要创建自己的专属文件,以便帮助我们更高效,快捷地完成任务。那么在Python中我们怎么创建并调用自己文件中的模块/函数呢? 在Python中调用自定义文件,通常是指调用自己编写的Python模块…

【C++】C++17结构化绑定、std::optional、std::variant、std::any

二十二、C17中的结构化绑定、std::optional、std::variant、std::any 本部分是一个小系列,介绍C17中新引入的、用来解决各种不同返回情况的、标准库新组件。 1、C的结构化绑定 结构化绑定structured bindings是C17中引入的一项特性,它允许开发者方便地…

ntkrnlmp.exe导致蓝屏死机的解决方法

在使用Windows操作系统的过程中,用户可能会遇到由ntkrnlmp.exe文件错误引发的蓝屏死机(Blue Screen of Death, BSOD)问题,这不仅影响了日常的工作效率,也可能造成数据丢失的风险。本文将为您提供一系列即时排查与修复n…

U3D游戏开发之骨骼动画相关

目录 1 作为U3D程序如何制作骨骼动画 2 骨骼动画程序代码相关 这个内容我在很久之前就想写了,很多项目也与骨骼动画挂钩,今天我们揭秘的是2D骨骼动画。来聊一聊大家可能非常关注的两个问题:作为程序如何制作骨骼动画?接到美术的骨…

java:题目:用Java实现简单的自取取款操作

import java.util.Scanner; public class ATM {public static void main(String[] args){//自主取款主类Scanner scnew Scanner(System.in);System.out.println("请输入账户号码:");String BankAccoutsrsc.nextLine();/BankAccout3 newBankAccoutnew Bank…

VLAN 高级技术 ——QinQ的配置

QinQ的概述: QinQ技术是一种扩展虚拟局域网(VLAN)数量空间的技术,通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来实现。以下是对QinQ技术的详细概述: QinQ技术的定义与背景 定义:QinQ&#xff08…

不得不承认供电公司信息宣传向媒体投稿的好方法找到了

初入国网供电公司,我被分配到了信息宣传部门,负责每月的信息宣传投稿任务。这项任务看似简单,实则充满挑战。一开始,我满怀热情,以为只要写出高质量的文章,就能顺利发表。然而,现实给了我当头一棒。传统的邮箱投稿方式,不仅竞争压力大,审核严格,而且周期漫长。每次投稿后,我总是…

『YOLOV5』| 一文搞定训练过程中的意外终止、以及想继续增加训练轮数!

文章目录 情况一:意外训练中断(程序未训练完成,想完成目标训练轮数)情况二:自动训练完成(程序已完成训练,想增加训练轮数) 情况一:意外训练中断(程序未训练完…

GCC编译器的`-Wall`、`-Wextra`和`-pedantic`选项解读

gcc是广泛使用的开源编译器,-Wall、-Wextra和-pedantic是gcc中用于控制警告信息的选项,以下是详细介绍: -Wall(启用大部分警告) 功能:-Wall 选项用于启用一系列常用的警告信息,这些警告能帮助…

MMBench-Video:上海 AI Lab 联合多所高校推出长视频理解基准测试工具,全面评估 LVLMs 视频理解的能力

❤️ 如果你也关注大模型与 AI 的发展现状,且对大模型应用开发非常感兴趣,我会快速跟你分享最新的感兴趣的 AI 应用和热点信息,也会不定期分享自己的想法和开源实例,欢迎关注我哦! 🥦 微信公众号&#xff…

高频电子线路---调角频谱与频宽

目录 调角频谱(FM单频调制) 带宽 调频方法 直接调频方法与电路 变容二极管 如何提升频偏? 1. 增大调制信号的幅度(增大调制深度) 2. 提高调制信号的频率 3. 提高调制深度(调制指数) 4. 增加发射功率 5. 使用特殊的调制…

摘要、数字签名、对称加密、非对称加密综合应用示例以及技术原理说明

图:介绍了数字信封的安全传输过程 关键术语 散列:Hash(哈希),一般翻译做散列、杂凑,是把任意长度的输入(数据信息)通过散列算法变换成固定长度的输出,该输出就是散列值…

java学习3---面向对象

一、设计对象并使用 1.类和对象 类是共同特征的描述;对象是真实存在的具体实例。 2.类的几个补充注意事项 二、封装 对象代表什么,就得封装对应的数据,并提供数据对应的行为。 封装告诉我们如何正确的设计对象 三、this关键字 this可以区…

Maven

Maven 命令方式构建项目 mvn compile:编译项目,生成target文件(不编译测试代码) mvn package:打包项目,生成jar或war文件(不指定默认jar包) mvn clean:清理编译或打包后…