LeetCode 面试经典 150_二叉树_二叉树中的最大路径和(77_124_C++_困难)(DFS)

LeetCode 面试经典 150_二叉树_二叉树中的最大路径和(77_124_C++_困难)

题目描述:

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和

输入输出样例:

示例 1:

输入 :root = [1,2,3]
输出 :6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入 :root = [-10,9,20,null,null,15,7]
输出 :42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

提示:

树中节点数目范围是 [1, 3 * 104]

-1000 <= Node.val <= 1000

题解:

解题思路:

思路一(深度优先搜索):

1、计算一个结点向下的最大路径和,就是计算左右子树的最大路径相加,再加上本结点的值(当然左右子树最大路径为负数时无需加左右子树)。为了进行上述的计算,我们需要从递归返回时进行操作,即从叶结点开始向上计算,这样我们就能方便的得到每个结点左右子树的最大路径和,进而得到当前结点的最大路径和。在这个过程中采用一个全局变量存储树中的最大路径和。

: 假设一个结点为root,左子树的最大路径和为leftSum,右子树的最大路径和为rightSum。

则当前结点的最大路径和为(root->val+leftSum+rightSum)这里leftSum和rightSum均大于等于0。

递归返回时我们需要返回:当前结点的值root->val+max(leftSum,rightSum)。这里leftSum和rightSum均大于等于0。(因为我们返回的是一条一直向下的路径)

2、复杂度分析:

① 时间复杂度:O(n),n代表二叉树中的结点数,需要遍历整个二叉树一次。

② 空间复杂度:O(n),n代表二叉树中的结点数,最坏情况下递归函数栈的深度是n。

代码实现

代码实现(思路一(深度优先搜索)):
cpp 复制代码
class Solution
{
private:
    //maxSum存储二叉树的最大路径
    int maxSum=INT32_MIN;
    
    //递归的求解最大路径
    int dfs(TreeNode *root){
        if (root==nullptr) return 0;

        //左子树向下的路径最大值
        int leftSum=max(dfs(root->left),0) ;
        //右子树向下的路径最大值
        int rightSum=max(dfs(root->right),0);

        //当前结点最大路径和
        int currentSum=root->val+leftSum+rightSum;
        //更新最大路径和
        maxSum=max(currentSum,maxSum);

        //返回当前结点左右子树中较大的路径
        return root->val+max(leftSum,rightSum);       

    }

public:
    //计算一个结点向下的最大路径,就是计算左右子树的最大路径相加再加上本结点
    //如果左右子树的最大路径为<0则不进行累加
    int maxPathSum(TreeNode *root){
        dfs(root);
        return maxSum;
    }
};
以思路一为例进行调试
cpp 复制代码
#include<iostream>
#include <vector>
#include <queue>
using namespace std;

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) {}
};

//通过数组创建二叉树,-1代表nullptr
TreeNode *createTree(const vector<int> &nums){
    if (nums.empty()) return nullptr;
    queue<TreeNode *> Q;
    TreeNode *root=new TreeNode(nums[0]);
    Q.push(root);
    int i=1;
    while (i<nums.size())
    {
        TreeNode *node=Q.front();
        Q.pop();
        if (nums[i]!=-1 )
        {
            node->left=new TreeNode(nums[i]);
        }
        ++i;
        if (nums[i]!=-1 && i<nums.size())
        {
            node->right=new TreeNode(nums[i]);
        }
        ++i;
    }
    return root;
    
}

//中序遍历输出二叉树,验证二叉树创建是否正确
void inorder(TreeNode *root){
    if(root==nullptr) return;
    inorder(root->left);
    cout<<root->val<<" ";
    inorder(root->right);
}

class Solution
{
private:
    //maxSum存储二叉树的最大路径
    int maxSum=INT32_MIN;
    
    //递归的求解最大路径
    int dfs(TreeNode *root){
        if (root==nullptr) return 0;

        //左子树向下的路径最大值
        int leftSum=max(dfs(root->left),0) ;
        //右子树向下的路径最大值
        int rightSum=max(dfs(root->right),0);

        //当前结点最大路径和
        int currentSum=root->val+leftSum+rightSum;
        //更新最大路径和
        maxSum=max(currentSum,maxSum);

        //返回当前结点左右子树中较大的路径
        return root->val+max(leftSum,rightSum);       

    }

public:
    //计算一个结点向下的最大路径,就是计算左右子树的最大路径相加再加上本结点
    //如果左右子树的最大路径为<0则不进行累加
    int maxPathSum(TreeNode *root){
        dfs(root);
        return maxSum;
    }
};

int main(int argc, char const *argv[])
{
    vector<int> nums={1,2,3};

    //通过数组创建二叉树,-1代表nullptr
    TreeNode *root= createTree(nums);
    
    //中序遍历验证二叉树创建是否正确
    // inorder(root);

    //计算二叉树中最大路径和并输出
    Solution s;
    cout<<s.maxPathSum(root);

    return 0;
}

LeetCode 面试经典 150_二叉树_二叉树中的最大路径和(77_124)原题链接

欢迎大家和我沟通交流(✿◠‿◠)

相关推荐
2501_941111682 小时前
模板编译期哈希计算
开发语言·c++·算法
序属秋秋秋2 小时前
《Linux系统编程之进程基础》【进程状态】
linux·运维·c语言·c++·笔记·操作系统·进程状态
xiaoxue..2 小时前
深入理解JavaScript中的深拷贝与浅拷贝:内存管理的艺术
开发语言·前端·javascript·面试
绝无仅有2 小时前
电商大厂面试题解答与场景解析(二)
后端·面试·架构
绝无仅有2 小时前
某电商大厂场景面试相关的技术文章
后端·面试·架构
Jeled3 小时前
RecyclerView ViewHolder 复用机制详解(含常见错乱问题与优化方案)
android·学习·面试·kotlin
利刃大大3 小时前
【c++中间件】etcd存储系统 && 服务注册 && 服务发现 && 二次封装
c++·中间件·服务发现·etcd·服务中心
报错小能手3 小时前
C++笔记 仿函数(函数对象)
开发语言·c++·笔记
草莓熊Lotso3 小时前
《算法闯关指南:优选算法--模拟》--39.替换所有问号,40.提莫攻击
开发语言·c++·算法·模拟