Leetcode题号124——二叉树中的最大路径和(C++版本,时间复杂度击败100%)

 声明::个人原创代码,转载请附上本文链接

题目:

题目要求

给定一个非空二叉树,计算其最大路径和。路径定义为从树中任意节点出发,沿父-子连接向下延伸的路径(不可分叉),路径和是路径中所有节点值的累加。路径至少包含一个节点,且不一定经过根节点。

关键点与变量对应
  • 路径方向:向下单向(左或右子树选其一)。

  • 核心变量

    • NodeMaxValue:当前节点为根的子树中,可能的最大路径和(包含左右子树的贡献)。

    • NodeAllowAddValue:当前节点能为父节点提供的最大贡献值(只能选择左或右路径)。

    • flag:标记是否已处理有效子节点贡献(用于初始化贡献值)。

思路分析

核心思想

通过递归计算每个节点的最大贡献值,并在递归过程中更新全局最大路径和。

递归函数目标
  1. 计算以当前节点为根的子树的最大路径和(可包含左右子树)。

  2. 计算当前节点能为父节点提供的最大贡献值(单边路径)。

贡献值规则
  • 子树的贡献值若为负,则舍弃(即取0)。

  • 当前节点的贡献值为 节点值 + max(左子树贡献, 右子树贡献)

全局最大值更新

每次递归时,计算当前节点的完整路径和(左+右+自身),并尝试更新全局最大值。

关键逻辑详解

1. 递归函数 GetOneNodeMaxValue 的流程
  • 输入:当前节点 root,全局最大值引用 MaxValue

  • 输出:当前节点能为父节点提供的最大贡献值 NodeAllowAddValue

  • 步骤分解

    1. 初始化

      • NodeMaxValue 初始化为当前节点的值,表示仅包含自身的路径和。

      • flag 标记是否已处理子节点贡献(初始为 false)。

    2. 处理左子树

      • 递归调用左子树,获取其贡献值 NodeLeftAllowMaxValue

      • 若左子树贡献值为正,则累加到 NodeMaxValue(表示选择左子树路径)。

      • 记录第一个有效子节点的贡献值到 NodeAllowAddValue,并标记 flag = true

    3. 处理右子树

      • 递归调用右子树,获取其贡献值 NodeRightAllowMaxValue

      • 若右子树贡献值为正,则累加到 NodeMaxValue(表示选择右子树路径)。

      • 比较左右子树的贡献值,更新 NodeAllowAddValue 为较大者,并确保 flag 标记正确。

    4. 更新全局最大值

      • 当前节点的完整路径和 NodeMaxValue(左+右+自身)可能与全局最大值 MaxValue 比较,取较大者。

    5. 返回贡献值

      • 返回 root->val + max(左贡献, 右贡献),确保路径只能向下延伸(单边选择)。

2. 全局最大值 MaxValue 的更新时机
  • 更新条件:当当前节点的完整路径和(包含左右子树)大于 MaxValue 时更新。

  • 意义:捕捉所有可能的路径组合,包括跨子树的路径(如示例中的根节点与左右子树组合)。

3. 贡献值的传递规则
  • 贡献值计算NodeAllowAddValue = max(左贡献, 右贡献)

  • 负值处理:若子树贡献值为负,则舍弃(等价于 max(0, 子树贡献))。

  • 返回值逻辑return (NodeAllowAddValue > 0) ? (root->val + NodeAllowAddValue) : root->val

代码 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 #include<climits>  // 包含INT_MIN的定义

class Solution {
public:
    // 递归函数:计算以当前节点为根的子树最大路径和,并更新全局最大值
    // 参数:root 当前节点,MaxValue 引用传递的全局最大值
    // 返回值:当前节点能为父节点提供的最大贡献值(只能选左或右路径)
    int GetOneNodeMaxValue(TreeNode*& root, int& MaxValue) {
        // 初始化当前节点的最大路径和为自身值(至少包含自己)
        int NodeMaxValue = root->val;  
        // 记录可传递给父节点的最大贡献值(单边路径)
        int NodeAllowAddValue;         
        // 标记是否存在有效子节点贡献(用于初始化贡献值)
        bool flag = false;

        // 处理左子树分支
        if(root->left != nullptr) {  // 存在左子树时递归处理
            // 递归获取左子树的贡献值(若为负则自动置0)
            int NodeLeftAllowMaxValue = GetOneNodeMaxValue(root->left, MaxValue);
            // 若左子树贡献值为正,则累加到当前路径和(选择左子树路径)
            if(NodeLeftAllowMaxValue > 0) NodeMaxValue += NodeLeftAllowMaxValue;
            // 初始化贡献值(首次处理子节点时记录左子树贡献)
            if(!flag) {  
                NodeAllowAddValue = NodeLeftAllowMaxValue;  // 保存左子树贡献值
                flag = true;                                // 标记已处理子节点
            }
        }

        // 处理右子树分支
        if(root->right != nullptr) {  // 存在右子树时递归处理
            // 递归获取右子树的贡献值(若为负则自动置0)
            int NodeRightAllowMaxValue = GetOneNodeMaxValue(root->right, MaxValue);
            // 若右子树贡献值为正,则累加到当前路径和(选择右子树路径)
            if(NodeRightAllowMaxValue > 0) NodeMaxValue += NodeRightAllowMaxValue;
            // 更新贡献值为左右子树中的较大者(确保单边路径)
            if(!flag || NodeAllowAddValue < NodeRightAllowMaxValue) {  
                NodeAllowAddValue = NodeRightAllowMaxValue;  // 更新为更大的贡献值
                if(!flag) flag = true;                        // 首次记录贡献值
            }
        }

        // 更新全局最大值(当前节点的完整路径和可能包含左右子树)
        if(NodeMaxValue > MaxValue) MaxValue = NodeMaxValue;  

        // 返回当前节点的贡献值(只能选择单边路径)
        // 若子节点有正贡献则加上,否则只返回自身值(断开子树)
        if(!flag) return root->val;  // 无子节点时直接返回自身值
        return NodeAllowAddValue > 0 ? root->val + NodeAllowAddValue : root->val;
    }

    int maxPathSum(TreeNode* root) {
        // 初始化全局最大值为最小整数(处理全负数树的情况)
        int MaxValue = 1 << 31;  // 等价于INT_MIN
        // 执行递归遍历整棵树,计算最大路径和
        GetOneNodeMaxValue(root, MaxValue);
        // 返回最终计算的全局最大路径和
        return MaxValue;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值