题目描述
知识点
树形DP
实现
码前思考
-
看见最优化的问题,我们基本上是要思考一下能不能使用DP来进行求解,虽然可能有时不行,但是一定要先思考能不能用DP,不能没有尝试就放弃DP思想;
-
这其实是一类非常常见的DP思想,为什么说常见呢?因为这个问题可以很好的转换成另外的问题;
-
问题转化
原始的问题其实我们是很难使用动态规划的,我们需要进行问题转换,使得转换后的问题满足最优子结构和重叠子问题。
我们知道所谓的Maximum Path Sum,它体现在树形结构上,一定是树中的某棵子树,那么我们的问题就变成了求树中所有结点为根的子树的Maximum Path Sum中的最大那个!上述问题转化的思想非常常见,例如我们的LIS和最大连续子序列和就是使用了这种思想,LIS是以某个字符结尾,最大连续子序列和是以某个数字结尾。
这类问题的典型特点就是,无法直接使用dp
进行索引得到问题答案,而是需要设置一个max
,min
变量来得到最终答案。而我们的背包问题则是可以直接通过dp[MAXN][MAXV]
索引得到答案的。 -
知道了怎么将问题进行转换了,接下来就是对转换后的问题进行求解。
-
这里需要特别注意一个问题,对于下图的情况:
-
理解了上图我们就可以放心的使用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;
}
}
};
码后反思
- 这类问题叫做树状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;
}
}
}
};