Every day a Leetcode
题目来源:124. 二叉树中的最大路径和
解法1:深度优先搜索
思路类似于:Leetcode543. 二叉树的直径,只是考虑对象从边变成了点。
首先,考虑实现一个简化的函数 dfs(node),该函数计算二叉树中的一个节点的最大贡献值,具体而言,就是在以该节点为根节点的子树中寻找以该节点为起点的一条路径,使得该路径上的节点值之和最大。
具体而言,该函数的计算如下:
-
空节点的最大贡献值等于 0。
-
非空节点的最大贡献值等于节点值与其子节点中的最大贡献值之和(对于叶节点而言,最大贡献值等于节点值)。
注意结点值有负数,如果 max(left_sum, right_sum) + node->val 为负数,那不如不添加这条路径,返回 0(即不采用这条路径)是更好的选择。
代码:
/*
* @lc app=leetcode.cn id=124 lang=cpp
*
* [124] 二叉树中的最大路径和
*/
// @lc code=start
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution
{
public:
int maxPathSum(TreeNode *root)
{
int ans = INT_MIN;
function<int(TreeNode *)> dfs = [&](TreeNode *node) -> int
{
if (node == nullptr)
return 0;
int left_sum = dfs(node->left);
int right_sum = dfs(node->right);
ans = max(ans, left_sum + right_sum + node->val);
return max(max(left_sum, right_sum) + node->val, 0);
};
dfs(root);
return ans;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n),其中 n 为二叉树的节点数,即遍历一棵二叉树的时间复杂度,每个结点只被访问一次。
空间复杂度:O(Height),其中 Height 为二叉树的高度。由于递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,而递归的深度显然为二叉树的高度,并且每次递归调用的函数里又只用了常数个变量,所以所需空间复杂度为 O(Height)。