110.平衡二叉树:
原题链接
思路:
既然要求比较高度,而二叉树里面的高度是:从当前节点到叶子节点的节点数。
既然是要到底部的,而我们的递归是从底部往上返回的,所以往上返回的时候,可以累加高度,故应该是后序遍历!自己可以多想想,很容易找到感觉。
而题目要求的平衡二叉树是左右子树的高度之差不大于1,而一棵二叉树有很多的子二叉树,子二叉树和二叉树之间的区别就是,所以这时候就要想到递归的思想。从下往上计算高度,然后逐渐往上累加,判断每棵以当前节点为根节点的子树的左右子树的高度之差是否满足条件!
- 明确递归的参数和返回值:参数:当前传入节点;高度:以当前传入节点为根节点的树的高度。(在左右子树都递归完后,然后进行统计计算高度之差,进行处理!)
- 那么如何标记左右子树的差值是否大于1呢?如果当前传入节点为根节点的二叉树已经不是平衡二叉树了,返回高度的话就毫无意义了,所以如果已经不是二叉树的话,可以返回-1来标记已经不符合平衡树的规则了。
- 明确终止条件:当前节点为空节点的时候,停止递归,返回0,表示当前节点为根节点的树的高度=0;
- 单层递归:如何判断以当前传入节点为根节点的二叉树是否平衡呢?当然是其左子树的高度和其右子树的高度的差值。分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1!表示已经不是平衡二叉树了!
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getHeight (TreeNode* root) {
//如果当前节点为空节点,则返回高度=0,表示以当前节点为根节点的子树的高度=0;
if (root == nullptr) {
return 0;
}
//计算左子树的高度:
int lh = getHeight(root->left);
//如果当前左子树的高度=-1,表示当前左子树的高度=-1;
if (lh == -1) {
return -1;
}
//计算右子树的高度:
int rh = getHeight(root->right);
if (rh == -1) {
return -1;
}
//统计左右子树的高度之差:
int res;
//如果此时的左右子树的高度之差大于1了,则说明此时的
if (abs(rh - lh) > 1) {
res = -1;
}
else {
//以当前节点为根节点的树的最大高度。
//从宏观角度来看的话,需要保证当前左子树的最大高度和右子树的最大高度满足条件
//所以返回的是当前节点为根节点的树的最大高度!
res = 1 + max(lh, rh);
}
return res;
}
bool isBalanced(TreeNode* root) {
return getHeight(root) == -1 ? false : true;
}
};
257. 二叉树的所有路径
原题链接:
思路:
本题是记录路径的,即从根节点出发,到达所有叶子节点的路径,其路径上的节点顺序是从上到下的。所以采用前序遍历,每次递归,记录一次路径上的节点。
- 递归的参数和返回值:参数:传入当前节点的子节点。返回值:
- 递归的出口:如果当前节点为空节点,则递归结束,该路径已经走完了,返回到根节点,走根节点的另一个子节点。
- 单层递归逻辑:
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<string> str;
void dfs (TreeNode* root, string s) {
if (root == nullptr) {
return ;
}
//如果当前节点为空节点,说明此时该收网了!
//未收网前,是在捕捉节点,因为存入的必须是一个字符串,而不是单个字符串
//把网弄好了,再收进str中!
//需要提前预判,防止末尾多加了一个 '->'
if (root->left == nullptr && root->right == nullptr) {
s += to_string(root->val);
str.push_back(s);
return ;
}
//前序遍历
s += to_string(root->val);
s += "->";
//递归搜索左子树;
dfs (root->left, s);
//递归搜索右子树:
dfs (root->right, s);
return ;
}
vector<string> binaryTreePaths(TreeNode* root) {
string s = "";
dfs (root, s);
return str;
}
};
404.左叶子之和
原题链接
思路:
问题的关键在于,如何判断当前节点是左叶子节点。
解决:当前节点为叶子节点的时候,再判断当前节点的父节点,父节点的子节点的左子节点和右子节点是否都为空!
如果是则为左叶子节点。反之不是!
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
//如果当前节点为空节点,则说明该节点的左叶子节点之和=0
if (root == nullptr) {
return 0;
}
//同理,如果当前节点为叶子节点,则说明该节点的左叶子节点之和=0
if (!root->left && !root->right) {
return 0;
}
//计算以当前节点为根节点的左子树的左叶子节点之和
int ls = sumOfLeftLeaves(root->left);
//判断当前节点为根节点的左子节点是否为左叶子节点,如果是的话,则进行答案上的计算。
if (root->left!=nullptr && !root->left->left && !root->left->right) {
ls = root->left->val;
}
//计算以当前节点为根节点的右子树上的左叶子节点之和。
int rs = sumOfLeftLeaves(root->right);
//计算以当前节点为根节点的子树的左叶子之和。
return ls + rs;
}
};