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;
    }
}

猜你喜欢

转载自www.cnblogs.com/jasminemzy/p/9656038.html