题目描述
给定一个二叉树,请计算节点值之和最大的路径的节点值之和是多少。
这个路径的开始节点和结束节点可以是二叉树中的任意节点
例如:
给出以下的二叉树,
返回的结果为6
解:
注意,这道题的节点值可以是负的,所以如果我们是数组的话直接就用DP表做了。但是这道题是树结构,而且路劲无限制,所以子结构处理上会麻烦一点,可能也就是为什么这道题是快手笔试里算是有点难度的题。
子结构推导:每条路径都是以某个节点作为根节点(子树任意)的一条路径,找到节点作为根节点的路径最大值,即子树(可不加子树,即为0)最大值加上本身值。所有节点最大值的最大值,就是整棵树的路径最大值。这也提醒我们,在分析子结构时,子结构最优解不一定是正确解,可能我们抽离出来的子结构解只是构成正确解的一部分,这跟01-背包问题要区分。像这道题,正确解不一定是该子结构中以该节点为根的路径,但是这样设计能将子结构连接。所以这道题,我们没有直接求子树正确解而是去求一个正确解的“一部分”,通过比较子结构最优解才获得正确解。
叶子节点出发,由下向上,每一个节点max=max(val+left.maxValue+right.maxValue),----child.max<0时置为0,即不加子树。注意,我们采用递归做法时,如果是返回给上一层,那么我们只可以是val+leftMax,或val+rightMax,否则路径就会重叠(不可能由 parent+left+right+grandParent 构成一个不重叠路径)。
import java.util.*;
import java.lang.Math;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型
*/
private int m; //辅助计算
public int nodeMax(TreeNode r){
if(r==null){
return 0;
}
//子树<0直接=0
int left=Math.max(nodeMax(r.left), 0);
int right=Math.max(nodeMax(r.right), 0);
//以该节点为根的路径最大值
m=Math.max(m, r.val+left+right);
//返回最优子树给父节点
return Math.max(r.val+left, r.val+right);
}
public int maxPathSum (TreeNode root) {
if(root==null){
return 0;
}
m=root.val;
nodeMax(root);
return m;
}
}