码迷,mamicode.com
首页 > 其他好文 > 详细

[Leetcode] Binary Tree Maximum Path Sum

时间:2014-12-03 23:05:58      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   ar   color   sp   for   on   

这是LeetCode上的一道题目,需要求二叉树中两点路径的最大和。原题是

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

Given a binary tree, find the maximum path sum.

The path may start and end at any node in the tree.

For example: Given the below binary tree,

       1
      /      2   3

Return 6.

 

大概的想法其实很简单,类似于用分治法求数组连续和的最大值。最大值有三种可能,第一种是起点和终点最大和在左子树中,第二种是起点和终点最大和在右子树中,第三种是起点在左子树中,终点在右子树中。第三种要求路径必须通过根节点,因此其左右子树中的路径只能是从左右子树的根节点到其中的某个节点。根据这个思路,就可以写出如下的代码。

class Solution {
public:
    int maxPathSum(TreeNode *root) {
        if(root==NULL)
            return 0;
        else{
            if(root->left==NULL && root->right==NULL)
                return root->val;

            int maxLeft = maxPathSum(root->left);
            int maxRight = maxPathSum(root->right);

            int maxLeafLeft = max(0, maxLeafSum(root->left));
            int maxLeafRight = max(0, maxLeafSum(root->right));
            int sumWithRoot = root->val + maxLeafLeft + maxLeafRight;

            return max(maxLeft, maxRight, sumWithRoot);
        }   
    }

    int maxLeafSum(TreeNode* root){
        if(root==NULL)
            return 0;
        else{
            if(root->left==NULL && root->right==NULL)
                return root->val;
            else{
                return root->val + max(maxLeafSum(root->left), maxLeafSum(root->right));   
            }   
        }   
    }
}


这个方法虽然结果是正确的,但是很不幸严重超时。虽然我知道瓶颈是出在maxLeafSum()上,这其中有很多的冗余计算,但是没有想到该如何优化。后来看了别人的解答,才发现自己对递归的理解还是不够深入。我参考了soulmachine的解答(顺便说一下,这个解答是我看过的最详细的解答了 https://github.com/soulmachine/leetcode ),他用的代码是

class Solution {
    public:
        int maxPathSum(TreeNode *root) {
            max_sum = INT_MIN;
            dfs(root);
            return max_sum;
        }   
    private:
        int max_sum;
        int dfs(const 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 = max(max_sum, sum);
            return max(r, l) > 0 ? max(r, l) + root->val : root->val;
        }   
};

这里的DFS就是返回从根节点到某个子节点的路径最大和。咋看一下似乎不对,怎么只考虑了路径通过根节点的情形呢,即开头我们讨论的第三种情形?这个地方的巧妙之处在于,我们所要求的最大和路径必定是满足其起点和终点在某个节点的两侧。所以只要我们用某个把这个函数应用到所有节点之上,把每次的计算结果与一个全局变量比较,就可以得到正确的结果。

非常巧妙的方法!这也说明递归有时候可以简化问题,甚至想得越简单越好,只要我们保证最优解肯定对于某个节点满足我们给定的形式。

 

用类似的办法可以计算二叉树所有节点中的最大值、最小值。

 

[Leetcode] Binary Tree Maximum Path Sum

标签:style   blog   http   io   ar   color   sp   for   on   

原文地址:http://www.cnblogs.com/darkphoton/p/4141417.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!