LeetCode 124. Binary Tree Maximum Path Sum

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

我们查看了下他们的反汇编代码, 发现:
这里写图片描述
差别果然还是蛮大的, 以后还是尽量使用标准库好了=_=!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值