代码随想录算法训练营day15 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和、222.完全二叉树的节点个数
110.平衡二叉树
需要知道左右子树的高度后才知道中间节点是否平衡,故采用后序遍历,只要找到一个不平衡的节点则不是平衡二叉树
使用全局变量bool is_balanced = 1;记录是否存在不平衡节点,出现不平衡节点则将该标志更新为0,表示不平衡
点击查看代码
class Solution {
public:
bool is_Balanced = 1; //全局变量,记录是否出现不平衡的节点
int getHeight(TreeNode *root) {
if(root == nullptr) return 0;
int LHeight = getHeight(root->left);
int RHeight = getHeight(root->right);
if(abs(LHeight - RHeight) > 1) is_Balanced = 0; //只要有一个不平衡节点,则不是平衡二叉树
return max(LHeight, RHeight) + 1;
}
bool isBalanced(TreeNode* root) {
getHeight(root);
return is_Balanced;
}
};
257.二叉树的所有路径
点击查看代码
class Solution {
public:
vector<string> result; //全局容器,在各层递归函数中共享,也可以写成引用参数放在形参中,能起到相同的作用
//递归遍历时,通过参数传递将path自顶向下传递
//注意path不是引用型,则各层函数各自维护自己的path
void getPath(TreeNode *root, string path) {
//if(root == nullptr) return; 由于左右递归函数前加了if判断,即空节点不会进入递归函数,故
//可无需此递归终止条件
if(root->left == nullptr && root->right == nullptr) {
result.push_back(path);
}
if(root->left != nullptr) { //root-left不为空才能操作root->left->val,必须加此if判断
getPath(root->left, path + "->" + to_string(root->left->val));
}
if(root->right != nullptr) {
getPath(root->right, path + "->" + to_string(root->right->val));
}
}
vector<string> binaryTreePaths(TreeNode* root) {
//由于节点数目大于等于1,不会出现空树情况,故无需对root进行判空
getPath(root, to_string(root->val));
return result;
}
};
本题思想与104.二叉树的最大深度的前序遍历解法思想完全一致,都是利用递归+回溯思想,通过“参数传递”自顶向下传递,本题中是将从根到下一层子节点的路径通过参数传递直接传给下一层的子节点,104则是将下层子节点的深度通过参数传递直接传给下一层的子节点,作为每层函数的局部变量各自维护。并设置全局变量/容器,在遇到叶子节点时,将路径同步入全局变量/容器vector
404.左叶子之和
点击查看代码
class Solution {
public:
int sum = 0; //全局变量,记录左叶子之和
void preOrder(TreeNode *root, TreeNode *parent) { //核心点是parent参数,即将父节点指针作为参数向下传递
if(root == 0) return;
//遇到叶子节点才处理
if(parent != nullptr && root->left == nullptr && root->right == nullptr) {
if(root == parent->left) sum += root->val;
}
preOrder(root->left, root);
preOrder(root->right, root);
}
int sumOfLeftLeaves(TreeNode* root) {
preOrder(root, nullptr);
return sum;
}
};
本题的关键点在于找到叶子节点后需要判断该叶子节点是否为其父节点的左孩子,而当前节点如何知道其父节点是谁呢?只需要将父节点指针通过参数传递的方式自顶向下进行传递即可,仍然是上一题的思想,每一个节点,每一层函数都维护了各自的父节点,仍然是递归+回溯的思想。
222.完全二叉树的节点个数
点击查看代码
class Solution {
public:
int countNodes(TreeNode* root) {
if(root == nullptr) return 0; //递归终止条件一:空树的节点个数计为0
//递归终止条件二:遇到满二叉(子)树,直接通过性质提前返回其节点个数,无需再递归计算
int LDepth = 1, RDepth = 1;
TreeNode *T_left = root->left, *T_right = root->right;
while(T_left) {
T_left = T_left->left;
++LDepth;
}
while(T_right) {
T_right = T_right->right;
++RDepth;
}
if(LDepth == RDepth) {
return pow(2, LDepth) - 1; //高度为LDepth的满二叉树节点个数 = 2的Ldepth次方 - 1
}
//以上为递归终止条件二,若不满足终止条件,则开始正式递归
int L_num = countNodes(root->left);
int R_num = countNodes(root->right);
return L_num + R_num + 1;
}
};
本题核心点在于递归终止条件二,要注意不是所有题目的递归终止条件都只有一个if(root == nullptr) return;,本题利用递归终止条件2,当遇到满二叉(子)树时,用公式直接得出节点个数进行返回,而无需再进行递归计算
2025/02/27
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!