leetcode124 - Binary Tree Maximum Path Sum - hard
Given a non-empty binary tree, find the maximum path sum.
For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.
Example 1:
Input: [1,2,3]
1
/ \
2 3
Output: 6
Example 2:
Input: [-10,9,20,null,null,15,7]
-10
/ \
9 20
/ \
15 7
Output: 42
树的分治法。DFS。
对某个root而言,定义one:包含该root往左右某一方向延伸,延伸到任意长度这条链上的和的最大值。two:包含该root往左右都延伸,延伸到任意长度这条链上和的最大值(只考虑严格双边的情况)。那么:
one = max(root.val, root.val + left.one如果有, root.val + right.one如果有)
two = max(root.val, root.val + left.one + right.one如果两边都有) (不用考虑退化成单边的形式,one已经帮你处理了)
在计算one,two的过程中给全局变量打个擂台,最后返回全局最大one和全局最大two其中大的那个。
细节:
1.因为观察计算,所需要的子数据只有one,所以不用新建resultType类,直接每次只返回one即可。two只是算一下打个全局擂台就抛弃了。
2.root == null的情况下不可以直接返回0. 如果返回0,那对负数的叶子节点比如-3,那这个按这样算出来的one, two结果就被抬高到0了,不正确。所以定义返回类型为Integer而不是int,这样碰null返null区分一下。同时这种情况下代码里每个地方写int还是写Integer都小心一点,避免自动转换类型造成代码错误。
3.最后的答案是全局打擂台产生的,而不是根节点的one, two其中之一。因为one的定义是带跟的,你要按这个错误的方法算的话那你就忽略了中间某段游离的one的情况了。
实现:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { private int oneMax = Integer.MIN_VALUE; private int twoMax = Integer.MIN_VALUE; public int maxPathSum(TreeNode root) { dfs(root); // P3: 答案不是root的one two其中大的那个,而应该是dfs过程中打擂台产生的。因为one的定义是经过root的一长条,那么这要求答案样子要么是经过root的,没有考虑到中间某一段one条。 return Math.max(oneMax, twoMax); } // P3: 巧妙用Integer类型的null表示null节点。 private Integer dfs(TreeNode root) { if (root == null) { // P1: 不可以return(0, 0),这样对负数的叶子节点不正确,把它们的one, two值抬高到0了。 // return new ResultType(0, 0); return null; } // P2: 这里别写成int left,那下面就对比不了null了。 Integer left = dfs(root.left); Integer right = dfs(root.right); int one = root.val, two = root.val; if (left != null) { one = Math.max(one, root.val + left); } if (right != null) { one = Math.max(one, root.val + right); } if (left != null && right != null) { two = Math.max(two, root.val + left + right); } oneMax = Math.max(oneMax, one); twoMax = Math.max(twoMax, two); return one; } }