1对称二叉树
给你一个二叉树的根节点 root
, 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
提示:
- 树中节点数目在范围
[1, 1000]
内 -100 <= Node.val <= 100
递归思路:
- 定义递归的函数功能:
- 比较左右子树是否对称
- 确定递归的结束条件:
- 当左节点和右节点都为空时,说明对称,返回true
- 当左节点和右节点其中一个为空时,说明不对称,返回false
- 当左节点和右节点的数值不相等时,说明不对称,返回false
- 确定递归的返回值:
- 返回左子树的左节点和右子树的右节点是否对称,以及左子树的右节点和右子树的左节点是否对称,两者都对称则返回true,否则返回false
- 在主函数中调用递归函数,判断整棵树是否对称。如果根节点为空,直接返回true;否则调用递归函数进行判断。
代码:
cpp
class Solution {
public:
// 递归函数,用于比较左右子树是否对称
bool compare(TreeNode* left, TreeNode* right) {
// 首先排除空节点的情况
if (left == NULL && right != NULL) return false;
else if (left != NULL && right == NULL) return false;
else if (left == NULL && right == NULL) return true;
// 排除了空节点,再排除数值不相同的情况
else if (left->val != right->val) return false;
// 此时左右节点都不为空,且数值相同的情况,继续递归判断子树
bool outside = compare(left->left, right->right); // 左子树的左节点和右子树的右节点比较
bool inside = compare(left->right, right->left); // 左子树的右节点和右子树的左节点比较
bool isSame = outside && inside; // 判断是否对称
return isSame; // 返回结果
}
// 主函数,判断整棵树是否对称
bool isSymmetric(TreeNode* root) {
if (root == NULL) return true; // 空树也算对称
return compare(root->left, root->right); // 调用递归函数比较左右子树
}
};
2完全二叉树的节点个数
给你一棵完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2h
个节点。
示例 1:
输入:root = [1,2,3,4,5,6]
输出:6
示例 2:
输入:root = []
输出:0
示例 3:
输入:root = [1]
输出:1
提示:
- 树中节点的数目范围是
[0, 5 * 104]
0 <= Node.val <= 5 * 104
- 题目数据保证输入的树是 完全二叉树
思路:
通过递归的方式计算一棵树的节点数。在递归函数中,先判断当前节点是否为空,若为空则节点数为0;然后递归计算左右子树的节点数,并将左右子树节点数之和加上当前节点即为当前子树的节点数。主函数调用递归函数计算整棵树的节点数,并返回结果。
代码:
cpp
class Solution {
private:
// 递归函数,用于获取以当前节点为根的子树的节点数
int getNodesNum(TreeNode* cur) {
// 当前节点为空,节点数为0
if (cur == nullptr) return 0;
// 递归获取左子树节点数
int leftNum = getNodesNum(cur->left); // 左
// 递归获取右子树节点数
int rightNum = getNodesNum(cur->right); // 右
// 当前节点的节点数为左右子树节点数之和加上当前节点
int treeNum = leftNum + rightNum + 1; // 中
return treeNum;
}
public:
// 主函数,计算整棵树的节点数
int countNodes(TreeNode* root) {
// 调用递归函数获取整棵树的节点数
return getNodesNum(root);
}
};
2迭代思路:
使用了队列来按层遍历整棵树,并统计节点的数量。首先将根节点压入队列,然后进入循环,每次循环先获取当前层节点的数量,然后对当前层节点进行遍历,依次取出节点,统计节点数量,并将节点的左右子节点(如果存在)压入队列。最终返回统计的节点数量。
代码:
cpp
class Solution{
public:
int countNodes(TreeNode* root){
queue<TreeNode* > que; // 定义一个队列用于存储节点
if(root !=nullptr) que.push(root); // 将根节点压入队列
int result =0; // 记录节点数量
while(!que.empty()){ // 循环直到队列为空
int size=que.size(); // 获取当前队列大小,即当前层节点数量
for(int i=0;i<size;i++){ // 对当前层节点进行遍历
TreeNode* node=que.front(); // 取出队首节点
que.pop(); // 弹出队首节点
result++; // 记录节点数量
if (node->left) que.push(node->left); // 左子树不为空则压入队列
if (node->right) que.push(node->right); // 右子树不为空则压入队列
}
}
return result; // 返回节点数量
}
};
3平衡二叉树
给定一个二叉树,判断它是否是
平衡二叉树
平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1。
示例 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
思路:
通过递归的方式来判断一个二叉树是否是平衡二叉树。其中getHeight函数用来计算以当前节点为根节点的二叉树的高度,如果不是平衡二叉树则返回-1。在计算当前节点的高度时,先递归计算左子树和右子树的高度,如果左子树或右子树不是平衡二叉树(高度为-1),则直接返回-1。然后再判断左右子树的高度差是否大于1,如果是则返回-1,否则返回当前节点为根节点的二叉树的高度。最后在isBalanced函数中判断整棵树的高度是否为-1,如果是则返回false,否则返回true
代码:
cpp
class Solution {
public:
// 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树则返回-1
int getHeight(TreeNode* node) {
if (node == NULL) {
return 0; // 如果节点为空,返回高度0
}
int leftHeight = getHeight(node->left); // 获取左子树的高度
if (leftHeight == -1) {
return -1; // 如果左子树不是平衡二叉树,直接返回-1
}
int rightHeight = getHeight(node->right); // 获取右子树的高度
if (rightHeight == -1) {
return -1; // 如果右子树不是平衡二叉树,直接返回-1
}
if (abs(leftHeight - rightHeight) > 1) { // 如果左右子树高度差大于1,则不是平衡二叉树
return -1;
} else {
return 1 + max(leftHeight, rightHeight); // 返回当前节点为根节点的二叉树的高度
}
}
bool isBalanced(TreeNode* root) {
int height = getHeight(root); // 获取二叉树的高度
if (height == -1) {
return false; // 如果高度为-1,则不是平衡二叉树
} else {
return true; // 否则是平衡二叉树
}
}
};
4使用唯一标识码替换员工ID
Employees
表:
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| id | int |
| name | varchar |
+---------------+---------+
在 SQL 中,id 是这张表的主键。
这张表的每一行分别代表了某公司其中一位员工的名字和 ID 。
EmployeeUNI
表:
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| id | int |
| unique_id | int |
+---------------+---------+
在 SQL 中,(id, unique_id) 是这张表的主键。
这张表的每一行包含了该公司某位员工的 ID 和他的唯一标识码(unique ID)。
展示每位用户的唯一标识码(unique ID );如果某位员工没有唯一标识码,使用 null 填充即可。
你可以以任意 顺序返回结果表。
返回结果的格式如下例所示。
示例 1:
输入:
Employees 表:
+----+----------+
| id | name |
+----+----------+
| 1 | Alice |
| 7 | Bob |
| 11 | Meir |
| 90 | Winston |
| 3 | Jonathan |
+----+----------+
EmployeeUNI 表:
+----+-----------+
| id | unique_id |
+----+-----------+
| 3 | 1 |
| 11 | 2 |
| 90 | 3 |
+----+-----------+
输出:
+-----------+----------+
| unique_id | name |
+-----------+----------+
| null | Alice |
| null | Bob |
| 2 | Meir |
| 3 | Winston |
| 1 | Jonathan |
+-----------+----------+
解释:
Alice and Bob 没有唯一标识码, 因此我们使用 null 替代。
Meir 的唯一标识码是 2 。
Winston 的唯一标识码是 3 。
Jonathan 唯一标识码是 1 。
思路:
通过左连接(left join)将两个表Employees和EmployeeUNI进行关联查询,关联条件是Employees表中的id字段与EmployeeUNI表中的id字段相等。查询结果包括了EmployeeUNI表中的unique_id字段和Employees表中的name字段,以展示每位员工的唯一身份ID和姓名。
代码:
sql
select
EmployeeUNI.unique_id, Employees.name
from
Employees
left join
EmployeeUNI
on
Employees.id = EmployeeUNI.id