题意分析
- 这个题目我们需要计算出一棵二叉树上面的所有的路径当中,找出路径的和最大的那个值。
- 这个题目的难点就是中途可能会存在权值为负数的情况,还有权值为0的情况不好处理。
- 这个题目还是有点意思的,我们可以用一个类似与树形DP的方法进行求解。
- 前缀知识,树形DP,树形DP就是我们假设我们知道了一棵二叉树的左右的子节点的最优值,然后我们可以传递到这个节点本身,最终传递到整棵树上面。
思路分析
解法一 DFS+树形DP
- 对于树的题目,很大程度上都可以使用搜索进行求解。这个题目也是一样的,使用一个先序遍历的思想,当我们进行递归的时候,我们先向左右子节点进行递归,求出左右子树的最优的情况返回,然后我们就可以更新这个节点的最优的情况了。
- 结合下面的图我们可以更好地理解我们如何进行递归。
- 接下来,我们就可以结合我们的代码进行理解了。具体请看注释
- 在进行DFS的时候可能会遍历所有的点,时间复杂度为O(n)
- 需要存储整个树的所有的结点的情况,空间复杂度为O(n)
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @return int整型
*/
// 注意,可能会存在权值为负数的节点,所以把这个先设置为负无穷
int ans=-0x3f3f3f3f;
int DFS(TreeNode* now){
// 这个是一个叶子节点
if(!now) return 0;
// 递归求出左右子树的最大的路径值
int left=DFS(now->left);
int right=DFS(now->right);
int nowSum=now->val;
if(left>0) nowSum+=left;
if(right>0) nowSum+=right;
// 更新这个节点,这条路径是这个节点的左右子树包括这个节点本身构成的
ans=max(ans,nowSum);
// 向上传递的时候只能三种方式进行传递
// 左+中,右+中,中这三种方法
return max(now->val,max(left,right)+now->val);
}
int maxPathSum(TreeNode* root) {
// write code here
ans=max(ans,DFS(root));
return ans;
}
};
解法二 BFS
- 和上面的DFS的思路一样,我们使用BFS进行求解,我们可以使用队列来进行一个层序遍历。我们先把这些结果都放到一个动态数组里面,然后我们从后往前面开始进行遍历,这其实就是我们从叶子节点到根节点开始进行访问,模拟了一个树形DP的一个过程。不断从叶子节点更新到根节点的,维护最终的答案。
- 代码如下
- 在进行BFS的时候可能存在遍历到所有的结点的信息的情况,时间复杂度为O(n)
- 需要对所有的结点的信息进行存储,空间复杂度为O(n)
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @return int整型
*/
vector<TreeNode*> node;
int ans=-0x3f3f3f3f;
queue<TreeNode*> q;
int maxPathSum(TreeNode* root) {
// write code here
if(!root){
return 0;
}
q.push(root);
// 进行一个层序遍历求出从根节点到叶子节点的所有节点
while(!q.empty()){
TreeNode* now=q.front();
q.pop();
node.push_back(now);
if(now->left) q.push(now->left);
if(now->right) q.push(now->right);
}
// 从后往前开始遍历
for(int i=node.size()-1;i>=0;i--){
TreeNode* now=node[i];
// 如果这个是叶子节点,那么直接比较
if(now->left==NULL&&now->right==NULL){
ans=max(ans,now->val);
}else{
// 不是叶子节点的情况,这个时候我们的左右子节点的最优值已经求出
int left=0,right=0;
if(now->left){
left=now->left->val;
}
if(now->right){
right=now->right->val;
}
int nowSum=now->val;
// 更新这个节点的最优值,要用于向上进行传递
now->val=max(now->val,max(left,right)+nowSum);
// 更新答案
ans=max(ans,max(now->val,left+right+nowSum));
}
}
return ans;
}
};