110. 平衡二叉树
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1
这里强调一波概念:
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
但leetcode中强调的深度和高度很明显是按照节点来计算的,如图:
求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)
本题求高度,所以采用后序
思路:
递归三步曲分析:
明确递归函数的参数和返回值
参数:当前传入节点。
返回值:以当前传入节点为根节点的树的高度。
那么如何标记左右子树是否差值大于1呢?
如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。
所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。
class Solution {
public:
/*
递归三要素
1、确定形参和返回值
形参:当前节点
返回:当前节点的高度
(跟递归后序求最大深度的思路是一样的)
2、明确终止条件
碰到空节点 返回的高度就是0
3、单层遍历条件
比较当前节点左右子树的高度 大于一就返回-1
小于等于1就返回这个节点的高度
*/
int getHeight(TreeNode* node) {
if (node == nullptr) return 0;
int leftH = getHeight(node->left);
if (leftH == -1) return -1;
int rightH = getHeight(node->right);
if (rightH == -1) return -1;
return abs(leftH - rightH) > 1 ? -1 : max(leftH , rightH) + 1;
}
bool isBalanced(TreeNode* root) {
return getHeight(root) == -1 ? false : true;
}
};
257. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
思路:
这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。
在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一一个路径在进入另一个路径。
前序遍历以及回溯的过程如图:
class Solution {
public:
//递归
/*
1、要通过中节点去找左右孩子,用前序遍历更方便
2、递归的终止条件:
这里是要找路径,找到一个就pushback一个
所以找到叶子节点就可以了。
判断叶子节点就是 cur!=null 但是左右为空
3、递归的返回值和形参
形参:1、当前节点 2、存放不同路径的容器result 3、记录当前节点的容器 path
无需返回值 result和path在传入的时候都以引用传入即可
4、单层逻辑
当前的节点加进path
遍历到叶子节点就把path放进reslut 说明拿到一条路径。同时pop 进行回溯
否则就继续遍历
*/
void traversal(TreeNode* node,vector<int>& path,vector<string>& result) {
path.push_back(node->val); //要先把遍历到的节点放进path
//上面就是在处理中
//写终止条件
if (node != nullptr&&node->left == nullptr&&node->right == nullptr) {
//把path里面的数据转成一条string放进result里面
string s;
for (int i = 0; i < path.size()-1; i++) {
s += to_string(path[i]);
s += "->";
}
s += to_string(path[path.size() - 1]);
result.push_back(s);
return;
}
//单层逻辑
if (node->left) {
traversal(node->left, path, result);
path.pop_back(); //回溯
}
if (node->right) {
traversal(node->right, path, result);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
vector<int> path;
if (root == nullptr) {
return result;
}
traversal(root, path, result);
return result;
}
};
404. 左叶子之和
给定二叉树的根节点 root ,返回所有左叶子之和
节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点
class Solution {
public:
/*
递归参数:当前节点 返回值就是左叶子的值
终止条件:当碰到空节点 返回0
碰到叶子节点(做中节点),其左孩子一定为空,所以也返回0
单层逻辑 :要通过父节点来判断是不是左叶子 是的话就返回
不是的话就继续便利
*/
int sumOfLeftLeaves(TreeNode* root) {
//终止条件
if (root == nullptr) return 0;
if (root->left == nullptr && root->right == nullptr) return 0;
int leftnum = sumOfLeftLeaves(root->left); //一路向左 找左叶子 找到以后会返回零
if (root->left != nullptr && root->left->left== nullptr && root->left->right == nullptr) { //return回来以后 通过父节点找到做叶子的值
leftnum = root->left->val;
}
//然后看当前父节点的右孩子有没有左叶子
int rightnum = sumOfLeftLeaves(root->right);
return rightnum + leftnum;
}
};