树形DP系列-leetcode124. 二叉树中的最大路径和,leetcode543.二叉树的直径

leetcode124. 二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

看到这题一开始整体的思路还是递归,对左右子树分别递归处理。如果dfs(root)表示以root为根的子树的最长路径和,dfs(left), dfs(right)分别表示左右子树的最长路径和,那么dfs(root)与dfs(left), dfs(right)的关系共有下面6种情况:

  • dfs(root) = root->val  //只取根节点
  • dfs(root) = dfs(left)   //只取左子树
  • dfs(root) = dfs(right) //只取右子树
  • dfs(root) = root->val + dfs(left) //取根节点和左子树
  • dfs(root) = root->val + dfs(right) //取根节点和右子树
  • dfs(root) = root->val + dfs(left) + dfs(right) //取根节点和左子树

但这样存在一个很明显的问题,如果左/右子树的最长路径和不包括root的左/右子节点,那么最长路径和root就不是连接的,这样2-6这5种情况都是有问题的。为了解决这个问题,我们对dfs(root)的假设进行加强,令 dfs(root)表示以root为根且经过root的最长路径长度,这样root和dfs(left)/dfs(right)就一定是连接上的。注意此时2,3种情况必须舍去了,因为更新后的值没有经过root,不符合dfs(root)的定义,dfs(root)对应下面4种情况。此外,由于dfs(root)的意思变了,为以root为根经过root的最长,最后dfs(root)不一定是全局的最长路径长度,因此需要一个全局变量maxlen记录最长路径长度,在每次递归时更新maxlen。

同时,对于情况6,是不能出现在递归条件中的,因为如果用6更新dfs(root),会导致root出现左右分支,这种情况是不可以把dfs(root)继续提交给父节点,作为父节点的一个子结构处理的,但是可以作为最大值的一个可能结果。

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
int maxsum = 0x80000000;
public:
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return maxsum;
    }

    // 返回以root为根,经过root的最大和
    int dfs(TreeNode* root)
    {
        if (root==NULL)
            return 0;
        int leftmax = dfs(root->left);
        int rightmax = dfs(root->right);
        int sum = root->val;
        sum = max(sum, root->val+leftmax);
        sum = max(sum, root->val+rightmax);
        sum = max(sum, root->val+leftmax+rightmax);

        maxsum = max(maxsum, sum);
        return root->val + max({0, leftmax, rightmax});
    }
};

 leetcode543.二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

这道题和上面一道题的思路基本一致

如果depth(root)表示以root为根且经过root的子树的最长直径,depth(left), depth(right)分别表示左右子树的结果,那么depth(root)的情况有下面种:

  • depth(root) = 1 + depth(left)  //取root和左子树
  • depth(root) = 1 + depth(right)  //取root和右子树
  • depth(root) = depth(left) + depth(right)  //取root和左右子树

同样,第3种情况不能作为递归条件。

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
     int ans=0;
public:
    int diameterOfBinaryTree(TreeNode* root) {
        depth(root);
        return ans;
    }

    int depth(TreeNode* root)
    {
        if (!root)  return 0;
        int l = depth(root->left);
        int r = depth(root->right);
        ans = max(ans, l+r);
        return 1+max(l, r);
    }
};

题目

 https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/

https://leetcode-cn.com/problems/diameter-of-binary-tree/

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值