【LeetCode】动态规划—124. 二叉树中的最大路径和(附完整Python/C++代码)

news2024/11/25 19:48:51

动态规划—124. 二叉树中的最大路径和

  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
      • 路径的限制:
    • 2. 理解问题和递推关系
      • 核心思路:
      • 状态定义:
      • 递归公式:
    • 3. 解决方法
      • 递归 + 动态规划方法
      • 伪代码:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
      • Python代码解释
  • C++代码
      • C++代码解释
  • 总结

题目描述

在这里插入图片描述
在这里插入图片描述

前言

二叉树中的最大路径和 是一个涉及到二叉树的经典动态规划问题。给定一棵二叉树,其中每个节点包含一个整数值,求出从任意节点开始到任意节点结束(路径上至少包含一个节点)的路径中的最大和。路径可以从树中的任意节点开始和结束,且必须沿着父节点和子节点之间的边走。

该问题的难点在于路径可以穿过树的任意部分,因此我们需要同时考虑左右子树的贡献,并且动态更新最大路径和。


基本思路

1. 问题定义

给定一棵二叉树,其中每个节点包含一个整数值,要求找到一条路径,使路径上的节点值之和最大。路径至少包含一个节点,且不一定经过根节点。

路径的限制:

  • 路径可以从任意节点开始,到任意节点结束。
  • 路径必须连续,并且只能沿父子节点的连接边进行。

2. 理解问题和递推关系

核心思路:

我们可以通过递归的方式来求解该问题。对于每个节点,我们有两种情况:

  1. 路径经过当前节点:我们可以将当前节点作为路径中的一部分,同时从左右子节点中选择贡献较大的部分。
  2. 路径不经过当前节点:在递归的过程中,每个节点的最大贡献值可以用来更新全局最大路径和。

状态定义:

  1. 递归函数 max_gain(node)

    • 该函数的作用是计算从当前节点出发的最大贡献值,也就是从当前节点延伸出去的路径的最大和。
    • 对于每个节点 node,它的最大贡献值等于:
      max_gain ( n o d e ) = max ⁡ ( 0 , max_gain ( n o d e . l e f t ) ) + max ⁡ ( 0 , max_gain ( n o d e . r i g h t ) ) + n o d e . v a l \text{max\_gain}(node) = \max(0, \text{max\_gain}(node.left)) + \max(0, \text{max\_gain}(node.right)) + node.val max_gain(node)=max(0,max_gain(node.left))+max(0,max_gain(node.right))+node.val
      其中,max_gain(node.left)max_gain(node.right) 分别表示左子树和右子树的最大贡献值,若某一侧的贡献值为负,则不应选择该侧路径(故取最大值和 0 进行比较)。
  2. 全局最大路径和 max_sum

    • 我们需要维护一个全局变量 max_sum,用于存储遍历过程中遇到的最大路径和。
    • 每次计算当前节点的路径和时,如果其和大于 max_sum,则更新 max_sum

递归公式:

  1. 对于每个节点 node,路径和的更新公式为:
    price_newpath = n o d e . v a l + max ⁡ ( 0 , max_gain ( n o d e . l e f t ) ) + max ⁡ ( 0 , max_gain ( n o d e . r i g h t ) ) \text{price\_newpath} = node.val + \max(0, \text{max\_gain}(node.left)) + \max(0, \text{max\_gain}(node.right)) price_newpath=node.val+max(0,max_gain(node.left))+max(0,max_gain(node.right))
    price_newpath 表示从左子树、右子树延伸到该节点的新路径的和。

  2. 更新全局最大路径和:
    max_sum = max ⁡ ( max_sum , price_newpath ) \text{max\_sum} = \max(\text{max\_sum}, \text{price\_newpath}) max_sum=max(max_sum,price_newpath)

  3. 返回从当前节点延伸到它父节点的最大贡献值:
    return value = n o d e . v a l + max ⁡ ( max_gain ( n o d e . l e f t ) , max_gain ( n o d e . r i g h t ) ) \text{return value} = node.val + \max(\text{max\_gain}(node.left), \text{max\_gain}(node.right)) return value=node.val+max(max_gain(node.left),max_gain(node.right))

3. 解决方法

递归 + 动态规划方法

  1. 定义递归函数 max_gain(node) 来计算从当前节点出发的最大贡献值。
  2. 在递归的过程中,动态更新全局最大路径和。
  3. 最终返回 max_sum,即全局最大路径和。

伪代码:

function maxPathSum(root):
    max_sum = -infinity
    
    function max_gain(node):
        if node is None:
            return 0
        
        left_gain = max(max_gain(node.left), 0)
        right_gain = max(max_gain(node.right), 0)
        
        price_newpath = node.val + left_gain + right_gain
        
        max_sum = max(max_sum, price_newpath)
        
        return node.val + max(left_gain, right_gain)
    
    max_gain(root)
    return max_sum

4. 进一步优化

  • 递归方式:通过后序遍历的方式(即先处理子节点,再处理父节点),以确保每个节点的最大路径和能正确地递归计算。
  • 时间复杂度:该算法的时间复杂度为 O(n),其中 n 为节点的个数。

5. 小总结

  • 问题思路:通过后序遍历递归求解,每个节点的最大路径和可以由其左子树和右子树的最大贡献值来决定。
  • 核心公式:路径和更新公式 price_newpath = node.val + left_gain + right_gain,最大贡献值的返回公式 return node.val + max(left_gain, right_gain)
  • 时间复杂度:时间复杂度为 O(n),适合处理中等规模的树形结构。

以上就是二叉树中的最大路径和问题的基本思路。


Python代码

class Solution:
    def maxPathSum(self, root: TreeNode) -> int:
        self.max_sum = float('-inf')  # 初始化最大路径和为负无穷
        
        # 递归函数,计算当前节点的最大贡献值
        def max_gain(node):
            if not node:
                return 0
            
            # 递归计算左右子树的最大贡献值,负数直接取0
            left_gain = max(max_gain(node.left), 0)
            right_gain = max(max_gain(node.right), 0)
            
            # 当前节点的路径和
            price_newpath = node.val + left_gain + right_gain
            
            # 更新全局最大路径和
            self.max_sum = max(self.max_sum, price_newpath)
            
            # 返回该节点的最大贡献值
            return node.val + max(left_gain, right_gain)
        
        # 调用递归函数计算
        max_gain(root)
        return self.max_sum

Python代码解释

  1. 初始化:定义全局变量 max_sum 来存储最大路径和,初始值设为负无穷。
  2. 递归计算:使用递归函数 max_gain(node),计算每个节点的最大贡献值,并动态更新 max_sum
  3. 返回结果:最终返回 max_sum,即二叉树中的最大路径和。

C++代码

class Solution {
public:
    int max_sum = INT_MIN;  // 初始化最大路径和为负无穷
    
    // 递归函数,计算当前节点的最大贡献值
    int max_gain(TreeNode* node) {
        if (!node) return 0;
        
        // 递归计算左右子树的最大贡献值,负数直接取0
        int left_gain = max(max_gain(node->left), 0);
        int right_gain = max(max_gain(node->right), 0);
        
        // 当前节点的路径和
        int price_newpath = node->val + left_gain + right_gain;
        
        // 更新全局最大路径和
        max_sum = max(max_sum, price_newpath);
        
        // 返回该节点的最大贡献值
        return node->val + max(left_gain, right_gain);
    }
    
    int maxPathSum(TreeNode* root) {
        max_gain(root);
        return max_sum;
    }
};

C++代码解释

  1. 初始化:定义全局变量 max_sum 来存储最大路径和,初始值设为 INT_MIN
  2. 递归计算:使用递归函数 max_gain(node),计算每个节点的最大贡献值,并动态更新 max_sum
  3. 返回结果:最终返回 max_sum,即二叉树中的最大路径和。

总结

  • 核心思想:通过后序遍历的方式递归求解二叉树中的最大路径和。每个节点的最大贡献值由左右子树的贡献值决定,同时更新全局最大路径和。
  • 动态规划的递归形式:利用递归求解左右子树的最大贡献值,再决定当前节点是否选择左子树、右子树的贡献来形成新的路径。
  • 时间复杂度:时间复杂度为 O(n),每个节点只访问一次,适合处理中等规模的二叉树问题。

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

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

相关文章

安装GraphRAG

安装GraphRAG 本文没有安装成功,一直卡在构建图节点。 我用的思路是GraphRAGOllama(大语言模型)Xinference(词嵌入)。找到的其他思路是,修改源码。 1 简介 1.1 GraphRAG GraphRAG是微软开源的一种基于…

鸿蒙开发 三十九 ArkTs类 class 静态属性和方法的定义

鸿蒙提供了static关键字,可以用static关键字修饰的属性和方法,用static修饰的属性和方法用类名.的方式调用,如下图: 在Robot方法中定义了静态的属性version,调用的话直接Robot.version就可以了,定义了方法&…

RabbitMQ消息队列MQ脑裂(网络分区)整理分析

文章目录 RabbitMQ 的集群架构基础什么是MQ脑裂检测网络分区RabbitMQ 网络分区导致脑裂的原因• 多个节点认为自己是主节点:• 节点间状态不一致:• 集群的不可用性和错误恢复: RabbitMQ 网络分区引发脑裂的常见场景队列镜像不同步HA&#xf…

人工智能的研究方法

一、人工智能是自然科学和社会科学的交叉学科 1、仿生学,生物构造和功能 2、运筹学,应用数学进行科学决策 3、控制论,通信与控制 4、认知科学,人脑或心智工件机制 5、哲学,世界观和方法论 6、数学,概…

Halcon Blob分析提取小光斑

文章目录 算子complement 返回一个区域的补集select_region_point 选择包含指定像素的所有区域intensity 计算灰度值的均值和偏差 案例 算子 complement 返回一个区域的补集 complement(Region : RegionComplement : : )Region (输入对象):这指的是输入的一个或多…

[Linux] 软硬链接

软硬连接是两种链接方式,目的是通过使用一个已有的文件,在不进行拷贝的情况下,可以在不同的路径下访问同一份文件 软连接相当于快捷方式 硬连接相当于引用计数 软硬链接的目标也可以是软硬链接 软连接 指令 : ln -s 源文件 链接文件 软连接可链接文件夹 链接文件被删除后文件…

复杂网络基本概念(二)

一、集聚系数 节点i的集聚系数定义: 节点i的k个邻居节点之间实际存在的边数E和总的可能边数之比 所有节点的集聚系数的平均值 二、网络稀疏性与连通性 完全连接网络: 如果一个网络中任意两个节点之间都有来连边存在,则称其是一个完全连接…

探索 Python 装饰器的新境界:wrapt 库的神秘力量

文章目录 探索 Python 装饰器的新境界:wrapt 库的神秘力量背景:为何选择 wrapt?wrapt 是什么?如何安装 wrapt?简单的 wrapt 库函数使用方法创建简单装饰器保持元信息处理参数传递 场景应用:wrapt 的实际用例…

某知名国企面试题

引言 金九银十,求职热潮再度来袭。最近,有位同学去一家知名国企应聘,回来后带回了一套面试题。这套面试题非常典型,其中包含了许多供应链金融方面的典型问题。这些问题很有分享的价值,大家也可以先自己独立思考一下&a…

38 Spring

38 Spring 参考资料 Spring-全面详解(学习总结) 基本概念 Spring理念 : 使现有技术更加实用 . 本身就是一个大杂烩 , 整合现有的框架技术。 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。 IOC本质 IOC全…

【Redis】分布式(day12)

引入 在实际生产中,只部署一个Redis时,就会造成单点问题: 可用性问题,单个节点部署的Redis,如果此时该服务器挂了,那么意味着Redis整体的服务也就断掉了。性能/并发也是比较有限的。 为了避免单点问题的…

如何在UE5中创建加载屏幕(开场动画)?

第一步: 首先在虚幻商城安装好Async Loading Screen,并且在项目的插件中勾选好。 第二步: 确保准备好所需要的素材: 1)开头的动画视频 2)关卡加载图片 3)准备至少两个关卡 第三步&#xff1a…

通信工程学习:什么是SPI串行外设接口

SPI:串行外设接口 SPI,即串行外设接口(Serial Peripheral Interface),是一种由Motorola公司首先在其MC68HCXX系列处理器上定义的同步串行接口技术。SPI接口主要用于微控制器(MCU)与外部设备之间…

spring |Spring Security安全框架 —— 认证流程实现

文章目录 开头简介环境搭建入门使用1、认证1、实体类2、Controller层3、Service层3.1、接口3.2、实现类3.3、实现类:UserDetailsServiceImpl 4、Mapper层3、自定义token认证filter 注意事项小结 开头 Spring Security 官方网址:Spring Security官网 开…

leetcode 1027 最长等差数列 题目的思考

https://leetcode.cn/problems/longest-arithmetic-subsequence/ 如果序列是:3 0 3,枚举的公差是3 对于第一个数3,它的序列长度就是他自己3 对于第二个数0,它的序列长度就行它自己0 对于第三个数,它的序列长度应该是【…

【未知列名注入】

简介 在sql注入中,如果服务器过滤了column_name阻止我们获取列名,我们该如何绕过 一、union 绕过 使用union构造多个表,把数据表和构造的123表连接起来,我们看一下构造过程: 查询user表数据 select * from user;Union联合查询…

基于协同过滤的景区旅游可视化与景区推荐系统(自动爬虫,地点可换)

文章目录 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主项目介绍过程展示项目移植每文一语 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主 项目介绍 本项目是一个综合性的旅游景区数据管理与分析推荐系统,集成了用…

Qt:设置程序图标与主窗口背景图片

目录 设置程序图标: 设置主窗口背景图片: 设置程序图标: 在设置图标之前先准备一张ico图标,没有ico图标的可以准备一张图片,然后找一个在线的ico转换网站去转换一张ico文件出来。 然后打开项目文件所在的文件夹&am…

C语言 | Leetcode C语言题解之第467题环绕字符串中唯一的子字符串

题目&#xff1a; 题解&#xff1a; #define MAX(a, b) ((a) > (b) ? (a) : (b))int findSubstringInWraproundString(char * p) {int dp[26];int len strlen(p);memset(dp, 0, sizeof(dp));int k 0;for (int i 0; i < len; i) {if (i && (p[i] - p[i - 1] …

Spark高级用法-数据源的读取与写入

目录 数据读取 数据写入 总结 数据读取 读文件 read.json read.csv csv文件有两个部分构成 头部数据&#xff0c;也就是字段数据&#xff0c;行数数据 read.orc 读数据库 read.jdbc(jdbc连接地址,table表名,properties{user用户名,password密码,driver驱动信息}) 缺少连…