题目链接:110. 平衡二叉树
思路
题目意思就是如果左子树和右子树的高度相差大于1就不是平衡二叉树,当是平衡二叉树就返回二叉树的高度,不是就返回-1,求高度一般用后序法
递归法(后序)
class Solution {
public:
int traversal(TreeNode* root) {
if (root == nullptr) return 0;
int lefthigth = traversal(root->left);
if (lefthigth == -1) return -1;
int righthigth = traversal(root->right);
if (righthigth == -1) return -1;
if (abs(lefthigth - righthigth) > 1) return -1;
else return max(lefthigth, righthigth) + 1;
}
bool isBalanced(TreeNode* root) {
return traversal(root) == -1? false : true;
}
};
递归三部曲
确定返回类型和参数类型:函数返回类型为int,代表高度或-1,参数类型为每个根
确定终止条件,就是可以确定结果的那一层,当遍历到叶子结点的下一层结点时,它们的高度为0
确定单层递归的逻辑:先得到左子树高度再得到右子树的高度,如果两边高度不符合条件则返回-1,符合条件则返回高度
值得注意的是返回后到达的是上一层的那个递归函数,如果这一层都返回-1了,那整棵棵树都是-1,所以直接在函数下面判断,如果下面一层都为-1了,后面全部返回-1了。
关键:终止条件后回到上一层递归函数的下一行
题目链接:257. 二叉树的所有路径
思路
求每二叉树的所有路径。第一个加入的就是根节点,而且自上向下加入,所以用前序遍历,因为加入的东西不能重复每条路径,不是遍历,所以需要弹出加入的点,用回溯
递归法(前序+回溯)
class Solution {
public:
void backtracking(TreeNode* root, vector<int>& path, vector<string>& result) {
path.push_back(root->val);
if (root->right == nullptr && root->left == nullptr) {
string sPath;
for (int i = 0; i < path.size() - 1; i++) {
sPath += to_string(path[i]);
sPath += "->";
}
sPath += to_string(path[path.size() - 1]);
result.push_back(sPath);
return;
}
if(root->left){
backtracking(root->left, path, result);
path.pop_back();
}
if(root->right){
backtracking(root->right,path,result);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root){
vector<string>result;
vector<int>path;
backtracking(root, path, result);
return result;
}
};
递归三部曲
确定返回类型和参数:返回类型为return,传入的参数为结果寄存数组和根结点
确定终止条件:当到达根结点时说明一条路径存储完毕,然后return,计入到参数结果数组中
确定单层递归的逻辑:每次到一个新结点都加入到一条结果集中,后面开始向左遍历当左边不为空时,向右遍历当右结点部位空时
问题
为什么要设置左右不为空呢?
因为遍历到2时还不是叶子结点,不是一个完整路径,为空就会去遍历右结点,知道遍历到叶子结点return,返回pop()
回溯的作用,其实就是返回上一层原本的情况,值什么都一样没改变
(二叉树)递归三原则--记住:做题不要想这个,要抽象
1.明白只有遍历完那颗树所有的分支才会真正不遍历那颗节点了(二叉树遍历完左右子树才算完结)
2.明白前中后序遍历需要遍历完哪些分支才会输出
3.明白返回上一层的return结果是交给那个递归函数的,下一层遍历就会从递归函数的下一行开始执行,且这一行一般是回溯的过程
题目链接:404. 左叶子之和
递归法(后序)
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == nullptr) return 0;
if (root->left == nullptr && root->right == nullptr) return 0;
int a = sumOfLeftLeaves(root->left);
if (root->left&&!root->left->left&&!root->left->right) {
a = root->left->val;
}
int b = sumOfLeftLeaves(root->right);
return a+b;
}
};
递归三部曲
确定返回类型和参数类型:返回类型是int,为左叶子之和,参数为根
确定终止条件:当遍历到最后叶子的下一个时因为没有左叶子可以确定结果,return0,但是叶子结点也可以确定结果也一样可以return0
确定单层递归的逻辑,算出左子树和右子树左叶子之和相加就是左叶子之和了,一般这个都是看根节点的逻辑的,看子节点的逻辑对这道题有更深刻的理解,代表左节点的数+右结点的数,一开始都为返回0,所以我们必须左叶子赋值。所以看最后三层是可以深刻理解的
如:倒数第一层左叶子返回0,右叶子也返回0,不可能让倒数第三层也返回0,所以需要加值。
更高明的方法,因为每个结点都只会遍历一次,所以判断这个点有没有左叶子,有左叶子就加入到sum中,最后返回就行了。