[LeetCode 124] - 二叉树最大路径和(Binary Tree Maximum Path Sum)
2013-06-08 22:02
585 查看
问题
给出一个二叉树,找到其中的最大路径和。路径可以从树中任意一个节点开始和结束。
例如:
给出如下二叉树,
1
/ \
2 3
返回6。
初始思路
为了简化分析,我们先假设二叉树中所有节点的值都是正数。通过观察可以发现,一棵二叉树的最大路径,就是其左子树的最大路径加上右子树的最大路径。看起来可以从根节点出发通过深度优先递归来求解:函数 查找路径
如果是叶子节点,返回叶子节点的值
如果不是叶子节点
左子树路径和 = 查找路径(左子树)
右子树路径和 = 查找路径(右子树)
如果[b]左子树路径+右子树路径和+当前节点值 > 当前最大路径,更新最大路径[/b]
返回[b][b]左子树路径+右子树路径和+当前节点值[/b][/b]
用题目中的简单例子来验证,是可以得出答案的。但是使用复杂一点的树来验证后就发现其中的问题了,如
1
/ \
2 3
/ \
4 5
使用前面的伪代码得出的结果是15,但是其实答案应该是11,由3,1,2,5或者2,4,5得到。分析可以发现问题在于计算2,4,5这棵子树时,它的最长路径为11,这是正确的。但是当它作为左子树向父节点返回最长路径时,因该返回7而不是11。因为从1出发不走重复路径不可能同时到达4或5的-通常二叉树节点路径的定义是每个节点只能访问一次,通过测试数据也可以验证题目就是这样要求的。因此我们需要两个最大值,一个是当前树的最大路径,即前面伪代码算出来的那个值;另一个是当前树向父节点提供的最大路径,这个值应该是根节点的值加上路径最长的子树那边的最大路径。我们向上层递归函数返回这个值。
好了,现在全是正数的情况解决了。让我们开始把负数引入。负数引入后,将会导致以下几个变化:
叶子节点的值也有可能成为最大路径。在全是正数的情形下,叶子节点的值肯定不可能会是最大路径,因为加上父节点的值后必然会变大。有了负数以后,这个情况就不成立了,如:
-1
/
3
这时最大路径就是3。
当前树最大路径的计算方法。有了负数以后不能简单的把左子树返回的值,右子树返回的值及当前的值相加了。这里我们把各种情况列举出来:
当前值为正,子树返回值都为正:全相加
当前值为正,子树返回值有一个为正:当前值+正的那个值,因为负值只会让结果变小。
当前值为正,子树返回值都是负:只取当前值,负值越加越小。
当前值为负,子树返回的值都为正:全相加,虽然值会变小,但是没有当前节点左右就不能联通。
当前值为负,子树返回值有一个为正:当前值+正的那个值。
当前值为负,子树返回值都为负:当前值,负值越加越小。
向父节点提供的最大路径的计算方法。和当前树最大路径计算方法基本一样。就是仍然要左子树右子树的值只能取大的那个。
将上面分析转换成代码,并加入一些细节如没有左(右)子树的判断。请注意由于节点的取值范围并没有限定,所以不能使用某个特殊值作为没有左(右)子树的标志。结果如下:
class Solution { public: int maxPathSum(TreeNode *root) { if(!root) { return 0; } maxSum_ = 0; firstValue_ = true; CountPathSum(root); return maxSum_; } private: int CountPathSum(TreeNode* root) { if(root->left == 0 && root->right == 0) { if(firstValue_ || root->val > maxSum_) { maxSum_ = root->val; firstValue_ = false; } return root->val; } else { int left = 0; int right = 0; if(root->left) { left = CountPathSum(root->left); } if(root->right) { right = CountPathSum(root->right); } int currentBest = 0; int sumInPah = 0; if(left > 0 && right > 0) { currentBest = left + right; sumInPah = left > right ? left : right; } else if(left > 0) { currentBest = left; sumInPah = left; } else if(right > 0) { currentBest = right; sumInPah = right; } else { if(!root->left) { currentBest = right; } else if(!root->right) { currentBest = left; } else { currentBest = left > right ? left : right; } sumInPah = currentBest; } //前面已做只取正值的处理,如果还小于零说明两个都是负数 if(sumInPah < 0) { sumInPah = root->val; } else { sumInPah += root->val; } if(currentBest < 0) { currentBest = root->val; } else { currentBest += root->val; } if(currentBest > maxSum_) { maxSum_ = currentBest; } return sumInPah; } } int maxSum_; bool firstValue_; };
maxPathSum
提交后Judge Small和Judge Large都顺利通过。
相关文章推荐
- Leetcode 124 Binary Tree Maximum Path Sum 二叉树最大路径和
- LeetCode(124) Binary Tree Maximum Path Sum 二叉树的最大路径和 (如何递归?)
- LeetCode | Binary Tree Maximum Path Sum(二叉树的路径最大值)
- Binary Tree Maximum Path Sum (二叉树路径和的最大值) 【leetcode】
- 124 Binary Tree Maximum Path Sum 求二叉树的最大路径和
- LeetCode(Binary Tree Maximum Path Sum) 在二叉树中找出一条和最大的路径
- [LeetCode] Binary Tree Maximum Path Sum 求二叉树的最大路径和
- [Leetcode] Binary tree maximum path sum求二叉树最大路径和
- LeetCode-Binary Tree Maximum Path Sum-二叉树最大路径和-DFS
- 【二叉树的递归】05二叉树中找任意起点和终点使他们的路径和最大【Binary Tree Maximum Path Sum】
- Binary Tree Maximum Path Sum 求二叉树的最大路径和
- JavaShowAlgorithm-Binary Tree Maximum Path Sum 二叉树最大路径和
- binary-tree-maximum-path-sum(二叉树的最大路径和)
- lintcode binary-tree-maximum-path-sum 二叉树中的最大路径和
- [LeetCode 124] Binary Tree Maximum Path Sum (DFS/二叉树)
- Binary Tree Maximum Path Sum 二叉树中任意路径的最大和
- [LeetCode] Binary Tree Maximum Path Sum(最大路径和)
- [LeetCode] Binary Tree Maximum Path Sum(最大路径和)
- LeetCode—***寻找二叉树中任意两个节点之间的最大值Binary Tree Maximum Path Sum
- [LintCode] Binary Tree Maximum Path Sum (二叉树中的最大路径和)