LeetCode------Binary Tree Maximum Path Sum

本文通过递归深度优先搜索解决二叉树最大路径和问题,详细解释了如何通过递归函数找到最大路径和,并提供了两种实现方式,一种使用全局变量,另一种使用ArrayList对象。

这里写图片描述

求二叉树的最大路径和是一道蛮有难度的题,难就难在起始位置和结束位置可以为任意位置,我当然是又不会了,于是上网看看大神们的解法,像这种类似数的遍历的题,一般来说都需要用DFS来求解,我们先来看一个简单的例子:
这里写图片描述
由于这是一个很简单的例子,我们很容易就能找到最长路径为7-11-4-13,那么怎么用递归来找出正确的路径和呢?根据以往的经验,树的递归解法一般都是递归到叶节点,然后开始边处理边回溯到根节点。那么我们就假设此时已经递归到结点7了,那么其没有左右子节点,所以如果以结点7为根结点的子树最大路径和就是7。然后回溯到结点11,如果以结点11为根结点的子树,我们知道最大路径和为7+11+2=20。但是当回溯到结点4的时候,对于结点11来说,就不能同时取两条路径了,只能取左路径,或者是右路径,所以当根结点是4的时候,那么结点11只能取其左子结点7,因为7大于2。所以,对于每个结点来说,我们要知道经过其左子结点的path之和大还是经过右子节点的path之和大。那么我们的递归函数返回值就可以定义为以当前结点为根结点,到叶节点的最大路径之和,然后全局路径最大值放在参数中,用结果res来表示。

在递归函数中,如果当前结点不存在,那么直接返回0。否则就分别对其左右子节点调用递归函数,由于路径和有可能为负数,而我们当然不希望加上负的路径和,所以我们和0相比,取较大的那个,就是要么不加,加就要加正数。然后我们来更新全局最大值结果res,就是以左子结点为终点的最大path之和加上以右子结点为终点的最大path之和,还要加上当前结点值,这样就组成了一个条完整的路径。而我们返回值是取left和right中的较大值加上当前结点值,因为我们返回值的定义是以当前结点为终点的path之和,所以只能取left和right中较大的那个值,而不是两个都要,参见代码如下:

public class solution{
    public int maxPathSum(TreeNode root) {
        max_sum = Integer.MIN_VALUE;
        //错误写法:如果定义递归时直接把max_sum当做参数传递进去则结果一直是Integer.MIN_VALUE.
        //因为Java是值传递,dfs拿到的是max_sum的副本,对它进行修改并不会影响到全局的max_sum.
        //dfs(root,max_sum);
        dfs(root);
        return max_sum;
    } 
    //维护一个全局变量max_sum,且没有把它当做参数直接传进去,在dfs方法中对max_sum的修改和赋值会直接影响到max_sum的值
    private int max_sum;

    private int dfs(TreeNode root) {
        if (root == null) return 0;
        int l = dfs(root.left);
        int r = dfs(root.right);
        int sum = root.val;
        if (l > 0) sum += l;
        if (r > 0) sum += r;
        max_sum = Math.max(max_sum, sum);
        return Math.max(r, l) > 0 ? Math.max(r, l) + root.val : root.val;
    }
}

我们应该尽量避免使用全局变量,所以这里其实可以用一个ArrayList对象来代替全局变量,代码如下:

public int maxPathSum(TreeNode root) {
    if(root==null)
        return 0;
    //维护一个ArrayList(避免使用全局变量),但其实只用到第一个位置
    ArrayList<Integer> res = new ArrayList<Integer>();
    res.add(Integer.MIN_VALUE);
    helper(root,res);
    return res.get(0);
}
private int helper(TreeNode root, ArrayList<Integer> res)
{
    if(root == null)
        return 0;
    int left = helper(root.left, res);
    int right = helper(root.right, res);
    int cur = root.val + (left>0?left:0)+(right>0?right:0);
    if(cur>res.get(0))
        res.set(0,cur);
    return root.val+Math.max(left, Math.max(right,0));
}
这段代码是一个经典的 **二叉树中的最大路径和**(LeetCode 第124题)的解法,使用了 **DFS(深度优先搜索) + 动态规划思想**。 你提供的代码使用了 C++14 以后的特性,如 **lambda 表达式递归(`this auto&& dfs`)** 和 **立即调用 lambda** 的方式来实现递归 DFS。这种写法在 LeetCode 等 OJ 平台上非常常见,但如果你希望在 **Visual Studio(VS)等标准编译器下编译运行**,这段代码 **可能无法通过编译**,因为 `this auto&& dfs` 这种写法不是标准 C++,而是某些编译器的扩展(比如 GCC 支持,但 MSVC 不支持)。 --- ### ✅ VS 兼容的完整版本(标准 C++17 写法) 下面是可以在 Visual Studio 上正常编译运行的完整版本: ```cpp #include <iostream> #include <algorithm> #include <climits> using namespace std; // Definition for a binary tree node. struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; class Solution { public: int maxPathSum(TreeNode* root) { int ans = INT_MIN; dfs(root, ans); return ans; } private: // 返回以当前节点为结尾的最大路径链和 int dfs(TreeNode* node, int& ans) { if (!node) return 0; // 递归左右子树 int left_gain = max(dfs(node->left, ans), 0); // 只取正值 int right_gain = max(dfs(node->right, ans), 0); // 当前节点作为最高点,计算路径和 int current_path_sum = left_gain + right_gain + node->val; ans = max(ans, current_path_sum); // 返回当前节点的最大链和(只能选一边) return max(left_gain + node->val, right_gain + node->val); } }; ``` --- ### ✅ 示例 main 函数(用于测试) ```cpp int main() { // 构造一个测试二叉树: // 1 // / \ // 2 3 TreeNode* root = new TreeNode(1); root->left = new TreeNode(2); root->right = new TreeNode(3); Solution sol; cout << "Maximum Path Sum: " << sol.maxPathSum(root) << endl; // 输出 6 // 清理内存 delete root->left; delete root->right; delete root; return 0; } ``` --- ### ✅ VS 编译注意事项: - **不支持 `this auto&& dfs` 写法**(这是 GCC 的扩展)。 - 使用标准的类成员函数或普通函数来递归是兼容性更好的方式。 - 使用 `std::function` 也可以实现递归 lambda,但效率略低。 --- ### ✅ 使用 `std::function` 的版本(兼容性较好) ```cpp #include <functional> int maxPathSum(TreeNode* root) { int ans = INT_MIN; function<int(TreeNode*)> dfs = [&](TreeNode* node) { if (!node) return 0; int l = max(dfs(node->left), 0); int r = max(dfs(node->right), 0); ans = max(ans, l + r + node->val); return max(l, r) + node->val; }; dfs(root); return ans; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值