Binary Tree Maximum Path Sum
题目描述
给出一颗二叉树,每个树节点有一个整数权值。
现在要求从树上找出一条路径,使得权值之和最大,问这个最大权值之和是多少。
算法分析
一开始我的想法是用树路径的倍增算法,然后找LCA什么之类的,结果发现都想歪了。
首先这里声明为每个树节点声明两个值:
- ans:以当前节点为根节点,且经过当前节点的路径的权值之和的最大值
- maxPath:以当前节点为根节点,同时以当前节点为路径端节点,所能求得的路径权值之和的最大值
那么我们有以下两个式子可以求得上述两个值:
- now.ans=left.maxPath+right.maxPath+now.val
- now.maxPath=max(left.maxPath,right.maxPath)+now.val
- left 为左儿子节点, right 为右儿子节点, val 表示节点权值。
显然,我们从所有节点的ans中选出最大的,就是题目要的结果。
因此我们只需要从根节点开始做一次DFS就得出结果。
注意:有一堆的细节问题。由于题目说的节点权值是可以为负数的,所以要特别处理负数(这会使得实际代码中的运算跟上述两个式子不同,但思想是一致的)。还有就是一些空节点之类的问题。
时间复杂度:O(n)
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxPathSum(TreeNode* root) {
if (root == NULL) return 0;
tree now= tree(root);
finalAns= now.ans;
dfs(now);
return finalAns;
}
private:
struct tree
{
TreeNode* node;
int ans;
int maxPath;
tree(TreeNode* t):node(t)
{
if (t==NULL)
{
ans=0;
maxPath=0;
}
else
{
ans=node->val;
maxPath=ans;
}
}
};
int finalAns;
void dfs(tree &now)
{
tree left = tree(now.node->left);
tree right = tree(now.node->right);
if (left.node == NULL && right.node == NULL)
{
if (now.ans>finalAns) finalAns=now.ans;
return;
}
if (left.node!=NULL) dfs(left);
if (right.node!=NULL) dfs(right);
if (left.maxPath > 0) now.ans+=left.maxPath;
if (right.maxPath > 0) now.ans+=right.maxPath;
now.maxPath+=max(max(left.maxPath,right.maxPath),0);
if (now.ans>finalAns) finalAns=now.ans;
}
};