题目描述
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root
,返回其 最大路径和 。
示例 1:

1 2 3
| 输入:root = [1,2,3] 输出:6 解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6
|
具体见题目详解。
算法思路
这是刷HOT100以来貌似碰到的第一个“困难”题目,不过所幸最后还是做出来了,我的思路很简单,首先肯定能想到这是个动态规划,但为什么是深搜呢?可以看我下面的分析。
计自身节点值为selfval
,左儿子节点路径值为leftval
,右儿子节点路径值为rightval
,则有:
- 对于一个节点,如果最终的路径中,其作为父节点,那么很明显,最大值必然在{selfval、selfval+leftval、selfval+rightval、selfval+leftval+rightval}中间产出。
- 如果其不是父节点,那么其只能贡献selfval, selfval + leftval, selfval + rightval之间最大的那一方给总路径,因为此时不然不可能同时拥有左右两个路径的值。
- 既然要知道
leftval
,rigthval
的大小关系,那么必然需要在求出最大值之前先求出后代的相应最大值,这样才能符合dp的思想,因此需要使用深搜。
我写出来的代码思路上和题解给的类似,但是还是存在一些不足,导致速率比较慢,源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution { void backsequence(TreeNode* root) { if (root == nullptr) { return; } int leftmax = INT16_MIN; int rightmax = INT16_MIN; if (root->left != nullptr) { backsequence(root->left); leftmax = max_lr[root->left]; } if (root->right != nullptr) { backsequence(root->right); rightmax = max_lr[root->right]; } max_lr[root] = max(root->val, max(root->val+leftmax, root->val+rightmax)); ans = max(ans, max(root->val, max(max(root->val + leftmax, root->val + rightmax), root->val + leftmax + rightmax))); } public: unordered_map<TreeNode*, int> max_lr; int ans; int maxPathSum(TreeNode* root) { ans = INT16_MIN; backsequence(root); return ans; } };
|
然后我又让claude3.7按照我的思路优化一下我的算法,他给出了如下结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Solution { private: int maxSum; int maxGain(TreeNode* node) { if (!node) return 0; int leftGain = max(maxGain(node->left), 0); int rightGain = max(maxGain(node->right), 0); int priceNewPath = node->val + leftGain + rightGain; maxSum = max(maxSum, priceNewPath); return node->val + max(leftGain, rightGain); } public: int maxPathSum(TreeNode* root) { maxSum = INT_MIN; maxGain(root); return maxSum; } };
|
比我的可读性好得多,也很容易理解,相信大家一看便会!