110.平衡二叉树
题目链接/文章讲解/视频讲解:代码随想录
1.代码展现
//110.平衡二叉树
int getHeight_balance(TreeNode* node) {
//step1 确定参数
//step2 确定中止条件
if (node == nullptr) {
return 0;
}
//step3 确定单层迭代逻辑
//这里使用后序遍历
//step3.1 判断左右子节点是否为平衡二叉树,不是的话返回-1
int leftHeight = getHeight_balance(node->left);
if (leftHeight == -1) {
return -1;
}
int rightHeight = getHeight_balance(node->right);
if (rightHeight == -1) {
return -1;
}
//中,对高度进行处理
//step3.2 非平衡二叉树的情况
if (abs(leftHeight - rightHeight) > 1) {
return -1;
}
//step3.3 正常情况下返回高度
return 1 + max(rightHeight, leftHeight);
}
bool isBalanced(TreeNode* root) {
if (getHeight_balance(root) == -1) {
return false;
}
return true;
}
2.本题小节
基本思路:首先要明确平衡二叉树的概念,本题的基础是求二叉树的深度,二叉树的深度十左子树和右子树中深度较大的决定的,此题判断是否为平衡二叉树,因此此题要判断的是左子树与右子树高度差不超过1。本题用得后序遍历,在处理父节点时的时候需要判断左右子树高度差,如果大于1,则返回-1;同时,处理左右节点时,如果出现了高度为-1,那么直接返回-1。
思考:本题是在求二叉树深度的基础上进行的扩展,高度差超过一的话,就必定不为平衡二叉树,一直向上返回-1即可。
257. 二叉树的所有路径
题目链接/文章讲解/视频讲解:代码随想录
1.代码展示
//257.二叉树的所有路径
void travelsal(TreeNode* node, vector<int>& vnTravel, vector<string>& vsResult) {
//step1 确定传入参数
//step2 确定终止条件
//由于本题是前序遍历,终止条件和后序遍历不一样
vnTravel.push_back(node->val); //中,
if (node->left == nullptr && node->right == nullptr) {
//叶子节点中,遍历轨迹并储存结果
string sTravel;
for (int i = 0; i < vnTravel.size(); i++) {
if (i == vnTravel.size() - 1) {
sTravel = sTravel + to_string(vnTravel[i]);
}
else {
sTravel = sTravel + to_string(vnTravel[i]) + "->";
}
}
vsResult.push_back(sTravel);
return;
}
//step3 确定单层遍历逻辑
//中,需要写在中止条件上面,否则叶子节点数据会丢失
//左
if (node->left) {
travelsal(node->left, vnTravel, vsResult);
//回溯
vnTravel.pop_back();
}
//右
if (node->right) {
travelsal(node->right, vnTravel, vsResult);
//回溯
vnTravel.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<int> vnTravel;
vector<string> vsResult;
if (root == nullptr) {
return vsResult;
}
travelsal(root, vnTravel, vsResult);
return vsResult;
}
2.本题小节
基本思路:本题使用的是前序遍历法,用得迭代和回溯解决的问题。本题之所以用前序遍历,是因为前序遍历的指向正好是从根节点指向叶子结点的,是一条路径。首先明确传入的参数,有node,收集路径点的vector容器以及储存结果的vector容器;然后是终止条件,与以前到叶子节点下的nullptr终止条件不同,本题到了叶子就终止了,因为到了这里就正好收集到了所有的路径,并且此时要将路径点取出,构建成string存入结果容器中;最后是单层迭代逻辑,首先是父节点,这里的父节点位置比较特殊,在中止条件之前,如果在终止条件后的话,会丢掉叶子节点的路径,然后是左子树节点,如过节点存在,则继续,调用迭代函数后,pop掉容器中的最后一个路径点(这是本题回溯的精华所在,画图就可以看见它的妙处),右子树节点也是一样的。
思考:本题的妙点就在于pop的处理,画图可以知道,走到叶子节点将结果储存后,pop掉最后的路径点,再进入另外一个叶子节点,储存好路径后,再pop掉最后一个路径点,返回到父节点中再pop一次最后的结果...实在是太妙了!!
404.左叶子之和
题目链接/文章讲解/视频讲解:代码随想录
1.代码展示
//404.左叶子之和
int sumOfLeftLeaves(TreeNode* root) {
//step1 确定参数
//step2 确定中止条件
//本题要求只用父节点
if (root == nullptr) {
return 0;
}
if (root->left == nullptr && root->right == nullptr) {
return 0;
}
//step3 单层迭代逻辑
//后序遍历
int numLeft = sumOfLeftLeaves(root->left);
int numRight = sumOfLeftLeaves(root->right);
//只在叶子结点的父节点操作
if (root->left != nullptr && root->left->left == nullptr && root->left->right == nullptr) {
numLeft = root->left->val;
}
return numLeft + numRight;
}
2.本题小节
本题思路:本题使用后序遍历法,首先确定参数为node;然后确定终止条件,这里再叶子节点下或者叶子节点处中止都可以,因为主要是对叶子节点的父节点操作;然后是单层迭代函数,左右调用迭代函数,对叶子结点的父节点进行操作,获取左叶子节点的值,在中返回左右节点之和。
思考:这一题并不是对所有的节点都进行处理的,而是选择性的对左叶子节点进行处理,因此会有一些限制条件,多思考,多画图!!