当前位置: 首页 > news >正文

LeetCode题练习与总结:二叉树中的最大路径和--124

一、题目描述

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例 1:

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

提示:

  • 树中节点数目范围是 [1, 3 * 10^4]
  • -1000 <= Node.val <= 1000

二、解题思路

  1. 使用递归的方式,后序遍历二叉树,对于每个节点,计算其左子树和右子树的最大路径和。
  2. 对于每个节点,其最大路径和可以是其左子树的最大路径和、右子树的最大路径和、或者节点值本身,取这三者的最大值。
  3. 同时,需要记录一个全局变量,用于保存遍历过程中的最大路径和。

三、具体代码

class Solution {private int maxSum = Integer.MIN_VALUE;public int maxPathSum(TreeNode root) {maxGain(root);return maxSum;}private int maxGain(TreeNode node) {if (node == null) {return 0;}// 计算左子树的最大路径和int leftGain = Math.max(maxGain(node.left), 0);// 计算右子树的最大路径和int rightGain = Math.max(maxGain(node.right), 0);// 计算当前节点的最大路径和,并更新全局最大路径和int priceNewPath = node.val + leftGain + rightGain;maxSum = Math.max(maxSum, priceNewPath);// 返回当前节点的最大路径和return node.val + Math.max(leftGain, rightGain);}
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 对于二叉树中的每个节点,我们都会调用一次 maxGain 函数。
  • 在 maxGain 函数中,我们对每个节点的左右子节点各调用一次 maxGain 函数。
  • 因此,每个节点只会被访问一次,所以时间复杂度是 O(N),其中 N 是二叉树中节点的数量。
2. 空间复杂度
  • 空间复杂度主要取决于递归栈的深度,这通常由树的高度决定。
  • 在最坏的情况下,树完全不平衡,每个节点都只有一个子节点,递归栈的深度将是 O(N)。
  • 在最好的情况下,树是完全平衡的,递归栈的深度将是 O(logN)。
  • 因此,空间复杂度在最坏情况下是 O(N),在最好情况下是 O(logN)。

综上所述,该算法的时间复杂度是 O(N),空间复杂度在最坏情况下是 O(N),在最好情况下是 O(logN)。

五、总结知识点

  1. 递归:这是一种常用的算法设计技巧,用于解决分而治之的问题。在这个问题中,我们使用递归函数 maxGain 来计算每个节点的最大路径和。

  2. 后序遍历:递归函数 maxGain 以后序遍历的方式访问二叉树的每个节点,即先访问左子树,然后是右子树,最后是当前节点。

  3. 二叉树的结构:代码中使用了 TreeNode 类来表示二叉树的节点,每个节点包含一个整数值 val 和两个指向其左右子节点的指针 left 和 right

  4. 路径和的计算:在递归函数中,我们计算每个节点的左子树和右子树的最大路径和,然后将它们与当前节点的值相加,得到经过当前节点的最大路径和。

  5. 全局变量的使用maxSum 是一个全局变量,用于在递归过程中记录遍历到的最大路径和。

  6. 边界条件的处理:当递归函数遇到空节点时,返回0,这表示如果子树的最大路径和为负,则可以忽略该子树。

  7. 数学函数的应用Math.max 函数用于在递归过程中选择最大的路径和。这是处理最大路径和问题时的一种常见技巧,因为路径和可能是由多个部分组成的,我们需要选择最大的那一个。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

相关文章:

  • pytorch中,load_state_dict和torch.load的区别?
  • JSONObject.toJSONString(***) json化后的值中的日期值被转换为时间戳?如何修改?
  • 源码文章上传无忧,论坛小程序支持
  • 人工智能GPT-4o?
  • 【AI基础】第三步:纯天然保姆喂饭级-安装并运行chatglm2-6b
  • 大型零售企业总部到分公司数据发放,有没有更优化的方案?
  • 知识图谱的应用---新零售
  • 【ARM Cache 及 MMU 系列文章 6 -- Cache 寄存器 CTR_EL0 | CLIDR | CCSIDR | CSSELR 使用详解 1】
  • SwiftUI 利用 Swizz 黑魔法为系统创建的默认对象插入新协议方法(六)
  • 小心人工智障
  • 【氵】Archlinux+KDE Plasma 6+Wayland 安装nvidia驱动 / 开启HDR
  • 正大国际期货:如何培养个好心态呢?
  • 【HarmonyOS】HUAWEI DevEco Studio 下载地址汇总
  • OBS+nginx+nginx-http-flv-module实现阿里云的推流和拉流
  • 电商比价系统的搭建需要哪些方面着手准备?
  • 【Amaple教程】5. 插件
  • AWS实战 - 利用IAM对S3做访问控制
  • CentOS7 安装JDK
  • conda常用的命令
  • Java编程基础24——递归练习
  • js中的正则表达式入门
  • Vue--数据传输
  • Vue小说阅读器(仿追书神器)
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 机器学习学习笔记一
  • 记录一下第一次使用npm
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 突破自己的技术思维
  • 微信小程序开发问题汇总
  • 我看到的前端
  • 用 Swift 编写面向协议的视图
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (28)oracle数据迁移(容器)-部署包资源
  • (Git) gitignore基础使用
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (分布式缓存)Redis持久化
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (南京观海微电子)——示波器使用介绍
  • (十一)手动添加用户和文件的特殊权限
  • (四) 虚拟摄像头vivi体验
  • (一) 初入MySQL 【认识和部署】
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (正则)提取页面里的img标签
  • (转)visual stdio 书签功能介绍
  • (转)德国人的记事本
  • (转载)利用webkit抓取动态网页和链接
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .Family_物联网
  • .net wcf memory gates checking failed
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?