LeetCode 124. Binary Tree Maximum Path Sum【树形DP模板】⭐⭐⭐

题目描述

在这里插入图片描述

知识点

树形DP

实现

码前思考

  1. 看见最优化的问题,我们基本上是要思考一下能不能使用DP来进行求解,虽然可能有时不行,但是一定要先思考能不能用DP,不能没有尝试就放弃DP思想;

  2. 这其实是一类非常常见的DP思想,为什么说常见呢?因为这个问题可以很好的转换成另外的问题;

  3. 问题转化
    原始的问题其实我们是很难使用动态规划的,我们需要进行问题转换,使得转换后的问题满足最优子结构重叠子问题
    我们知道所谓的Maximum Path Sum,它体现在树形结构上,一定是树中的某棵子树,那么我们的问题就变成了求树中所有结点为根的子树的Maximum Path Sum中的最大那个!

    上述问题转化的思想非常常见,例如我们的LIS最大连续子序列和就是使用了这种思想,LIS是以某个字符结尾,最大连续子序列和是以某个数字结尾。
    这类问题的典型特点就是,无法直接使用 dp 进行索引得到问题答案,而是需要设置一个 maxmin 变量来得到最终答案。而我们的背包问题则是可以直接通过 dp[MAXN][MAXV] 索引得到答案的。

  4. 知道了怎么将问题进行转换了,接下来就是对转换后的问题进行求解。

  5. 这里需要特别注意一个问题,对于下图的情况:
    在这里插入图片描述

  6. 理解了上图我们就可以放心的使用DFS来实现最优子结构重叠子问题了。

代码实现

//使用动态规划进行解题
//我们知道一个路径一定是有一个根结点的!不信?你可以试试举个反例出来
//使用DFS求解

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    int ans;
public:
    int maxPathSum(TreeNode* root) {
        ans = INT_MIN;
        dfs(root);
        return ans;
    }

    int dfs(TreeNode* root){
        if(root == NULL){
            return 0;
        }else{
            //如果此树不为空
            int lmax = dfs(root->left);
            int rmax = dfs(root->right);
            int curmax;
            
            //有三种情况
            curmax = max(root->val,root->val+lmax);
            curmax = max(curmax,root->val+rmax);
            curmax = max(curmax,root->val+rmax+lmax);

            if(curmax > ans){
                ans = curmax;
            }

            //返回的max
            int returnmax;
            returnmax = max(root->val,root->val+lmax);
            returnmax = max(returnmax,root->val+rmax);

            return returnmax;
        }
    }
};

码后反思

  1. 这类问题叫做树状DF感觉好高级的样子,难道是指在树结构上运用DP中的最优子结构重叠子问题思想吗?
    感觉这类问题最大的特点就是没有了dp数组,完全通过DFS来实现最优子结构和重叠子问题。

二刷代码

二刷代码真的写的好丑!

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 //树形DP
class Solution {
public:
    int maxv = INT_MIN;
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return maxv;
    }

    int dfs(TreeNode* root){
        if(root==NULL){
            return 0;
        }else{
            int cur = root->val;
            int left = dfs(root->left);
            int right = dfs(root->right);

            if(left<0&&right<0){
                if(cur>maxv){
                    maxv=cur;
                }
                return cur;
            }
            
            if(left<0&&right>=0){
                maxv = max(maxv,cur+right);
                return cur+right;
            }

            if(left>=0&&right<0){
                maxv = max(maxv,cur+left);
                return cur+left;
            }

            maxv = max(maxv,cur+left+right);
            
            if(cur+left>cur+right){
                return cur+left;
            }else{
                return cur+right;
            }

        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值