1. 题目描述
Given a 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 does not need to go through the root.
For example:
Given the below binary tree,
1
/ \
2 3
Return 6.
2. 解题思路
拿到这道题目, 基本的想法还是使用递归, 我们递归计算通过每个节点的最大路径和 ( left + right + val), 与通过该节点的最大子路径的分支(max(left, right) + val), 每次更新一下最大路径和就可以了。考虑到, 可能会有大量重复分支被计算, 我们这里借助一个map存放每个节点 的 左右最大子路径的分支的和。 ie, 使用带备忘录的自上而下的递归算法。
3. code
特别注意, 如果不加 mymap.clear(), vs2013 和 leetcode 都是可以出正确结果的, 但是牛课的oj 不可以, 以后还是尽量注意下初始化的问题好了。
class Solution {
public:
int maxPathSum(TreeNode* root) {
mymap.clear(); // 这句话一定要加, 如果不加的牛课的OJ 通过不了
int maxsum = root->val;
computePathSum(root, maxsum);
return maxsum;
}
private:
//************************************
// Method: computePathSum
// FullName: Solution::computePathSum
// Access: private
// Returns: int 返回经过 root 的下方路径中最大的值
// Qualifier:
// Parameter: TreeNode * root
// Parameter: int & maxsum 记录所经过的所有路径的最大值
//************************************
int computePathSum(TreeNode * root, int & maxsum){
if (root == nullptr)
return 0;
if (mymap.find(root) == mymap.end()){
// 因为经过 root->left 的节点可能会小于 0, 这时候, 这部分节点可以不用遍历了
// 直接从root 节点出发就可以了
int left = max(computePathSum(root->left, maxsum), 0);
int right = max(computePathSum(root->right, maxsum), 0);
mymap.insert(make_pair(root, vector<int>{left, right}));
}
// 计算路径 root 节点的 path 的最长路径和
int sum = mymap[root][0] + mymap[root][1] + root->val;
// 更新 maxsum
maxsum = maxsum >= sum ? maxsum : sum;
// 返回root 路径下方最长的路径和
return max(mymap[root][0], mymap[root][1]) + root->val;
}
unordered_map<TreeNode *, vector<int>> mymap;
};
4. 大神代码
虽然理论上使用带备忘录的递归算法, 效率应该更快些, 不过这里似乎不是这样, 这段代码比我们快很多。也就是说, 我们的代码中维护一个map 消耗掉的时间效率是巨大的。
int maxPathSum(TreeNode *root) {
int maxPath = INT_MIN;
dfsMaxPath(root, maxPath);
return maxPath;
}
int dfsMaxPath(TreeNode *root, int &maxPath) {
if (!root) return 0;
int l = max(0, dfsMaxPath(root->left, maxPath));
int r = max(0, dfsMaxPath(root->right, maxPath));
maxPath = max(maxPath, l + r + root->val);
return root->val + max(l, r);
}
同时需要注意的是:
maxsum = maxsum >= sum ? maxsum : sum;
maxsum = max(maxsum, sum);
他们两者之间也是存在差别的, 我们提交之后, 可以看到仅仅因为这句话的不同, 运行时间差了10ms
我们查看了下他们的反汇编代码, 发现:
差别果然还是蛮大的, 以后还是尽量使用标准库好了=_=!!