https://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.
解题思路:
这是二叉树遍历比较难得题目,反正我没做出来。
先看看题意,这个最大路径可能是是从树的任意节点到任意节点。开始和结束节点都无需是叶节点或者根节点,甚至路径也可以不经过根节点。任意,于是便没有眉目。
我们思考这个问题。因为路径可能是经过任何节点的,那么这个问题就一定要以每一个节点为root,然后在以它为root的所有路径中找到一个最大值。再在这些所有的最大值中间取一个最大的,就是问题的结果。这里的路径,是无向的,也就是可以从下至上,再从上至下。
第二步很简单,就是维护一个变量,不断去更新他即可。问题是,前一步如何做?
我们考虑任意节点为root,那么以这个节点为root的路径的最大值,一定是它左子树的最大值 + root.val + 右子树的最大值。注意,这里的最大值是有向的,一定是从上至下(或者从下至上,结果是一样的)。当然,如果左子树或者右子树的最大值<0,就不要加上他们。
所以,要解决第一步。我们定义了一个递归的方法,返回的是,从root节点往下的有向路径的最大值。
递归到每个节点的时候,我们都去取它左子节点往下的最大值,和右子节点往下的最大值,然后再去得出从左到右以root为根的路径的最大值。
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public int maxPathSum(TreeNode root) { int[] max = new int[]{Integer.MIN_VALUE}; dfs(root, max); return max[0]; } public int dfs(TreeNode root, int[] max) { if(root == null) { return 0; } int leftMax = dfs(root.left, max); int rightMax = dfs(root.right, max); int maxFromRoot = root.val; if(leftMax > 0) { maxFromRoot += leftMax; } if(rightMax > 0) { maxFromRoot += rightMax; } max[0] = Math.max(max[0], maxFromRoot); return Math.max(root.val, root.val + Math.max(leftMax, rightMax)); } }
这题要特别注意,递归方法返回的不能是maxFromRoot。要清晰的理解递归方法的定义。这里的dfs方法,并不是直接求解最大路径的方法,而是用来递归求每个节点往下的有向路径的最大值。最大路径的计算过程,是通过max这个变量,在递归过程中间自动维护的。
为什么max要用一个数组?因为Java中方法参数传递都是pass by value,不能by reference。对象的内容除外,比如数组,或者list的内容。这里的除外也不是真的除外,是指可以达到by reference的效果。具体不明白的,可以自己去研究一下Java的对象、栈、堆。
http://blog.csdn.net/linhuanmars/article/details/22969069
http://fisherlei.blogspot.sg/2013/01/leetcode-binary-tree-maximum-path-sum.html
update 2015/05/18:
二刷,做了出来,但是想想怎么表述比较清楚。
对于任意节点root,另它左子树的最大和为left,右子树最大和为right。那么,经过它的最大路径和一定是root.val+left(如果left>0)+right(如果right>0)。
所以,更新全局最大max的时候,我们需要对每个节点,都做一次这个动作。
那么递归计算left或者right的时候,left一定是有向的,即从上倒下,不可能从下到上,再到下。比如下图,计算11这个点的最大和,那么一定是11+7+2。但是遍历到4时,最大和一定是4+11+7,而不能是4+11+7+2。因为递归到左子树的时候,只能取11+7,而不能是11+7+2。
所以,具体的递归过程,只能在root.val, root.val+left, root.val+right中间取最大的那个,返回作为当前节点往下的最大和。
但是更新全局最大的时候,要用root.val, root.val+left, root.val+right, root.val+left+right去更新max。
这样表述可能清楚点。
关键是,弄清楚自己写的递归方法的真正定义。以及,如何更新max,这两者其实是完全不同的动作。
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1

浙公网安备 33010602011771号