https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/
题目要求:
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例 1:
输入: [1,2,3] 1 / \ 2 3 输出: 6示例 2:
输入: [-10,9,20,null,null,15,7] -10 / \ 9 20 / \ 15 7 输出: 42核心思路:如果一个节点对路径的贡献值是负数,很明显,我们就并不需要这个节点,我们只要贡献值为正数的节点
假设有如下二叉树
如何想要知道当前节点对路径的贡献值,首先就需要知道其左右子节点对路径的贡献值,所以我们需要先递归至二叉树的最深层,然后从最深层开始回溯
由于是左递归优先执行,所以我们先递归至左侧最深处的叶子节点 9
叶子节点 9 没有左右节点,所以其左右节点对路径的贡献值为 0 ,即对于节点 9 来说,其 leftGain = 0,rightGain = 0
于是,回溯至节点 9 ,节点 9 路径的贡献值 = 节点 9 本身的贡献值 + max(节点 9 左节点的贡献值, 节点 9 右节点的贡献值) = 9 + 0 = 9 ,此时路径最大值暂时等于 9
此时最大的路径值 = 节点 9 本身的贡献值 + 节点 9 左节点的贡献值 + 节点 9 右节点的贡献值 = 9 + 0 + 0 = 9
此时开始往二叉树的右边开始递归,递归至叶子节点 -10 ,该节点对路径的贡献值为 -10 ,不考虑,对于叶子节点 -6 也是同样的道理
回溯至节点 15 ,其左右子节点的贡献值被当成 0 计算(因为贡献值为负数,还不如不走),路径长度为 15,比之前的 9 大,所以路径最大值暂时等于 15
节点 15 对路径的贡献值 = 节点 15 本身的贡献值 + max(节点 15 左节点的贡献值, 节点 15 右节点的贡献值) = 15 + 0 = 15
执行完左递归后,执行右递归,节点 7 的左右子节点的贡献值分别为 8、9
此时回溯至节点 7
如果抛去上一层节点不看,按照 8 --> 7 --> 9 的走法,路径长度为 8 + 7 + 9 = 24 ,比之前的 15 大,所以路径最大值暂时等于 24
如果节点 7 作为上层节点的中间节点,左右子节点只能选择一个,那么选择 7--> 9 的走法,路径值为 7 + 9 = 16 ,则是节点 7 对上层节点的路径最大贡献值
此时回溯至节点 20
如果抛去上一层节点不看,按照 15 --> 20 --> 7 --> 9 的走法,路径长度为 15 + 20 + 7 + 9 = 51,比之前的 24 大,所以路径最大值暂时等于 51
如果节点 20 作为上层节点的中间节点,左右子节点只能选择一个,那么选择 20 --> 7--> 9 的走法,路径值为 20 + 7 + 9 = 36 ,则是节点 20 对上层节点的路径最大贡献值
此时回溯值根节点 -10 ,根节点对路径的贡献值为负数,当做 0 处理
代码
/** * @ClassName MaxPathSumDemo * @Description TODO * @Author Heygo * @Date 2020/9/3 12:07 * @Version 1.0 */ public class MaxPathSumDemo { public static void main(String[] args) { TreeNode node1 = new TreeNode(-10); TreeNode node2 = new TreeNode(9); TreeNode node3 = new TreeNode(20); TreeNode node4 = new TreeNode(15); TreeNode node5 = new TreeNode(7); TreeNode node6 = new TreeNode(-10); TreeNode node7 = new TreeNode(-6); TreeNode node8 = new TreeNode(8); TreeNode node9 = new TreeNode(9); // 构造二叉树 node1.left = node2; node1.right = node3; node3.left = node4; node3.right = node5; node4.left = node6; node4.right = node7; node5.left = node8; node5.right = node9; int maxGain = maxPathSum(node1); System.out.println(maxGain); } static int maxSum = Integer.MIN_VALUE; public static int maxPathSum(TreeNode root) { maxGain(root); return maxSum; } public static int maxGain(TreeNode node) { if (node == null) { return 0; } // 递归计算左右子节点的最大贡献值 // 只有在最大贡献值大于 0 时,才会选取对应子节点 int leftGain = Math.max(maxGain(node.left), 0); int rightGain = Math.max(maxGain(node.right), 0); // 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值 int priceNewpath = node.val + leftGain + rightGain; // 更新答案 maxSum = Math.max(maxSum, priceNewpath); // 返回节点的最大贡献值 return node.val + Math.max(leftGain, rightGain); } public static class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } }