参考labuladong的博客刷一下二叉树的题目,主要是记录下来理清自己的思路,如果有需要修改的地方还请大家不吝赐教~会根据刷题数量不断更新~
二叉树的遍历问题的递归框架如下:
/*
*struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
*};
*/
void traverse(TreeNode* root) {
if(root == NULL ) return;
//前序遍历 cout << root -> val;
traverse(root -> left);
//中序遍历 cout << root -> val;
traverse(root -> right);
//后序遍历 cout << root -> val;
}
Leetcode#124
题目描述
解题思路
从最简单的case出发,假设有一颗由三个节点组成的树,a为根节点,b和c分别为左、右子节点,可能存在的路径情况为:
- 左子树的最大路径➕当前根节点,即 b + a
- 右子树的最大路径➕当前根节点,即 c + a
- 左子树的最大路径➕右子树的最大路径➕当前根节点,即 b + a + c
那么每一步我们需要判断的是以左节点为根节点的左子树和以右节点为根节点的右子树的最大路径哪个更大,返回其中更大的一个,该最大路径是只包含上升路径的,没有下降路径的,即只包含形似b-a或c-a路径,不包含形似b-a-c的路径。因此在递归中我们需要返回的值是左子树和右子树中更大的路径和。但是最终需要返回的结果是所有子树中的最大路径和,因此需要设置一个全局变量来记录递归过程中所有子树的最大路径和。
仅仅有上文的思路可以写出代码,但是想要通过全部样例,还要考虑负数的处理问题。当某条路径和为负数时,我们必然会舍弃它,可以使用max(0,x)
语句来舍弃负数。
考虑一种特殊情况,当所有节点的数值都为-1时,总树的根节点是不能舍弃的,因此全局最大和的初始值应该设置为INT_MIN而不是0,以此避免舍弃所有节点的情况。
实现代码
/**
* 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 {
public:
/**
对于任意一个节点, 如果最大和路径包含该节点, 那么只可能是两种情况:
1. 其左右子树中所构成的和路径值较大的那个加上该节点的值后向父节点回溯构成最大路径
2. 左右子树都在最大路径中, 加上该节点的值构成了最终的最大路径
**/
int ans = INT_MIN;
int maxPathSum(TreeNode* root) {
int sidemax = OneSideMax(root);
return ans;
}
int OneSideMax(TreeNode* root) {
if(root == nullptr) return 0;
// 如果子树路径和为负则应当置0表示最大路径不包含子树
int left = max(0, OneSideMax(root -> left));
int right = max(0, OneSideMax(root -> right));
// 判断在该节点包含左右子树的路径和是否大于当前最大路径和
ans = max(ans, left + right + root -> val);
return max(left, right) + root -> val;
}
};