110.平衡二叉树
题目描述:
给定一个二叉树,判断它是否是平衡二叉树
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true示例 2:
输入:root = [1,2,2,3,3,null,null,4,4] 输出:false示例 3:
输入:root = [] 输出:true提示:
- 树中的节点数在范围
[0, 5000]
内-104 <= Node.val <= 104
平衡二叉树:该二叉树中任意一个节点的左右子树的高度差不超过1
实现思路:
因为我们要求的是二叉树中节点的高度,因此需要使用后序遍历,因为后序遍历是将左右孩子的情况返回给父节点,父节点再根据左右孩子的高度再+1,层层往上返回,因此求的是高度,而前序遍历是由上到下去遍历,因此求解的是深度
使用递归来实现:
1.确定函数的参数和返回值,传入的应该是根结点,返回值是左右子树的高度
2.确定函数终止条件,如果发现空节点,则返回0
3.单层递归的逻辑,后序遍历,发现不满足平衡二叉树,则返回-1,如果发现满足则返回左右孩子高度的最大值+1
代码:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ //求高度 int getdepth(struct TreeNode *root) { if(!root) return 0; int ldepth = getdepth(root->left); int rdepth = getdepth(root->right); return ldepth > rdepth ? ldepth+1 : rdepth+1; } bool isBalanced(struct TreeNode* root) { if(!root) return true; int ldepth = getdepth(root->left); int rdepth = getdepth(root->right); if( abs(ldepth-rdepth) > 1 ) return false; //检查是否为平衡二叉树 return isBalanced(root->left) && isBalanced(root->right); }
257.二叉树的所有路径
题目描述:
给你一个二叉树的根节点
root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5] 输出:["1->2->5","1->3"]示例 2:
输入:root = [1] 输出:["1"]提示:
- 树中节点的数目在范围
[1, 100]
内-100 <= Node.val <= 100
递归思路:
使用前序遍历的方法,因为只有使用前序遍历,才能按照题目的要求输出
按照递归三部曲的思路:
1.确定函数的参数和返回值,要返回为空,参数应该传入二叉树的根节点和存放二叉树的单个路径的地址,存放所有二叉树路径的数组
2.确定函数的终止条件,当遍历到叶子节点(即左右孩子为空),对于叶子节点,将当前路径转换成字符串,并添加到结果数组中
3.单层递归的逻辑,对于非叶子节点,递归遍历其左右子树,并更新当前路径
代码:
void path(struct TreeNode *root, char **paths, int *returnSize, int *sta, int top) { if(root != NULL) { // 如果节点不为空 if(!root->left && !root->right) { // 如果是叶子节点 // 分配内存存储路径字符串 char *tem = (char *)malloc(1001); int len = 0; // 将路径节点转换成字符串形式 for(int i = 0; i < top ; i++) len += sprintf(tem + len , "%d->", sta[i]); sprintf(tem + len, "%d", root->val); // 将路径字符串添加到结果数组中 paths[(*returnSize)++] = tem; } else { // 如果不是叶子节点,将当前节点值添加到路径中,继续遍历左右子树 sta[top++] = root->val; path(root->left, paths, returnSize, sta, top); path(root->right, paths, returnSize, sta, top); } } } char** binaryTreePaths(struct TreeNode* root, int* returnSize) { // 分配内存存储路径数组 char **paths = (char **)malloc(sizeof(char *) * 1001); // 初始化路径数量为0 *returnSize = 0; int sta[1001]; // 调用递归函数遍历二叉树 path(root, paths, returnSize, sta, 0); return paths; }
解释:
sprintf
函数是一个格式化输出函数,用于将格式化的数据写入字符串中第一个参数
tem + len
是指要写入的目标字符串的起始位置,tem
是分配的存储路径字符串的指针,len
是当前已经写入的字符数,所以tem + len
确保新的字符追加到当前字符串的末尾第二个参数
"%d->"
是格式化字符串,表示要将整数 (%d
) 转换成字符串并追加 "->"第三个参数
sta[i]
是要转换成字符串的整数值所以,
sprintf(tem + len, "%d->", sta[i]);
的作用是将整数值sta[i]
转换成字符串并追加到路径字符串的末尾,并在其后添加 "->",以构建完整的路径字符串。
404.左叶子之和
题目描述:
给定二叉树的根节点
root
,返回所有左叶子之和。示例 1:
输入: root = [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24示例 2:
输入: root = [1] 输出: 0提示:
- 节点数在
[1, 1000]
范围内-1000 <= Node.val <= 1000
思路:
叶子节点:左右孩子都为空
左叶子节点:该节点是其父节点的左孩子,且是叶子节点
判断思路:
当我们查到到某个节点时,判断它的左孩子节点是否为空,再判断它的左孩子是否是叶子节点,因为当我们实际遍历到叶子节点时,我们无法判断它是左孩子还是右孩子
递归后序遍历实现过程:
1.判断函数的参数和返回值,返回值为左叶子节点和,参数应该为根节点
2.判断递归函数的终止条件,如果根节点为空,返回0,如果遇到叶子节点,也返回0
3.单层递归逻辑,递归向左遍历收集左叶子数,并进行记录,注意此时递归到的是其父节点,递归向右遍历收集左叶子数,最后进行相加
代码实现:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ int sumOfLeftLeaves(struct TreeNode* root){ if(!root) return 0; if(!root->left && !root->right) return 0; //向左遍历 int lsum = sumOfLeftLeaves(root->left); //当前节点左孩子不为空,该左孩子是叶子节点 if(root->left && !root->left->left && !root->left->right) lsum = root->left->val; //记录该值 //向右遍历 int rsum = sumOfLeftLeaves(root->right); return lsum + rsum; //处理根节点 }