一、二叉树的最大深度
1.题目
Leetcode:第 104 题
给定一个二叉树 root
,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:3
示例 2:
输入:root = [1,null,2] 输出:2
2.解题思路
使用递归法和迭代法遍历二叉树,计算二叉树的最大深度
3.实现代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// 定义一个结构体TreeNode,用于表示二叉树的节点。
struct TreeNode {
int val; // 存储节点的值。
TreeNode* left; // 指向该节点左子树的指针。
TreeNode* right; // 指向该节点右子树的指针。
// TreeNode的构造函数,用于创建一个TreeNode实例。
// 参数x是节点的值,left和right默认为NULL,表示没有左右子节点。
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
// 一、二叉树的最大深度(递归法)
class Solution1 {
public:
// 定义名为getdepth的辅助函数,用于递归地计算二叉树节点的深度。
// 函数接受一个参数:指向二叉树节点的指针node。
int getdepth(TreeNode* node) {
if (node == NULL) return 0; // 如果传入的节点为空,说明已经到达了叶子节点的下方,返回深度0。
int leftdepth = getdepth(node->left);// 递归地计算左子树节点的深度。
int rightdepth = getdepth(node->right); // 递归地计算右子树节点的深度。
int depth = 1 + max(leftdepth, rightdepth); // 计算当前节点的深度,为左子树和右子树中的最大深度加1(当前节点本身)。
return depth;// 返回当前节点的深度。
}
// 定义名为maxDepth的成员函数,用于返回二叉树的最大深度。
// 函数接受一个参数:指向二叉树根节点的指针root。
int maxDepth(TreeNode* root) {
return getdepth(root);// 调用getdepth函数计算并返回整棵树的最大深度。
}
};
// 二、二叉树的最大深度(迭代法)
class Solution2 {
public:
// 定义名为maxDepth的公共成员函数,用于计算并返回二叉树的最大深度。
// 函数接受一个参数:指向二叉树根节点的指针root。
int maxDepth(TreeNode* root) {
if (root == NULL) return 0; // 如果传入的根节点为空,说明是一棵空树,返回深度0。
int depth = 0;// 初始化深度变量为0,用于记录二叉树的最大深度。
queue<TreeNode*> que; // 创建一个队列que,用于存储待访问的节点。
que.push(root);// 将根节点入队。
while (!que.empty()) { // 使用while循环进行遍历,直到队列为空。
int size = que.size();// 获取队列中的节点数量。
depth++; // 增加深度计数,每遍历完一层,深度就增加1。
for (int i = 0; i < size; i++) {// 遍历当前层的所有节点。
TreeNode* node = que.front(); // 取出队列前端的节点。
que.pop();// 将节点从队列中移除。
if (node->left) que.push(node->left);// 如果节点有左子节点,将其入队,以便后续遍历。
if (node->right) que.push(node->right);// 如果节点有右子节点,将其入队,以便后续遍历。
}
}
return depth;// 返回记录的最大深度。
}
};
//测试
// 辅助函数,用于创建一个新的TreeNode
TreeNode* createNode(int value) {
return new TreeNode(value);
}
// 辅助函数,用于构建二叉树
TreeNode* buildTree(vector<int>& values) {
if (values.empty()) return NULL;
TreeNode* root = createNode(values[0]);
queue<TreeNode*> queueNode;
queueNode.push(root);
int i = 1;
while (!queueNode.empty()) {
TreeNode* node = queueNode.front();
queueNode.pop();
if (i < values.size()) {
node->left = createNode(values[i++]);
queueNode.push(node->left);
}
if (i < values.size()) {
node->right = createNode(values[i++]);
queueNode.push(node->right);
}
}
return root;
}
// 打印容器中的所有元素,用于验证测试结果
void printVector(const vector<int>& vec) {
for (int value : vec) {
cout << value << " ";
}
cout << endl;
}
// 主函数
int main() {
vector<int> treeValues = { 1, 2, 3, 4, 5, 6, 7 };// 定义二叉树的层序遍历结果,用于构建二叉树
TreeNode* root = buildTree(treeValues); // 构建二叉树
Solution1 s1;// 创建Solution类的实例
Solution2 s2;
int result1 = s1.maxDepth(root);// 传入二叉树的根节点
int result2 = s2.maxDepth(root);
cout << "二叉树的最大深度(递归法)是: " << result1 << endl;
cout << endl;
cout << "二叉树的最大深度(迭代法)是: " << result2 << endl;
cout << endl;
return 0;
}
二、二叉树的最小深度
1.题目
Leetcode:第 111 题
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6] 输出:5
2.解题思路
使用递归法和迭代法遍历二叉树,计算二叉树的最小深度
3.实现代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// 定义一个结构体TreeNode,用于表示二叉树的节点。
struct TreeNode {
int val; // 存储节点的值。
TreeNode* left; // 指向该节点左子树的指针。
TreeNode* right; // 指向该节点右子树的指针。
// TreeNode的构造函数,用于创建一个TreeNode实例。
// 参数x是节点的值,left和right默认为NULL,表示没有左右子节点。
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
// 一、二叉树的最小深度(递归法)
class Solution1 {
public:
// 定义名为getDepth的辅助函数,用于递归地计算二叉树节点的深度。
// 函数接受一个参数:指向二叉树节点的指针node。
int getDepth(TreeNode* node) {
if (node == NULL) return 0;// 如果传入的节点为空,说明是一棵空树,返回深度0。
int leftDepth = getDepth(node->left); // 递归地计算左子树节点的深度。
int rightDepth = getDepth(node->right);// 递归地计算右子树节点的深度。
// 如果当前节点的左子树为空,但右子树不为空,则当前节点的深度等于右子树深度加1。
if (node->left == NULL && node->right != NULL) {
return 1 + rightDepth;
}
// 如果当前节点的右子树为空,但左子树不为空,则当前节点的深度等于左子树深度加1。
if (node->left != NULL && node->right == NULL) {
return 1 + leftDepth;
}
// 如果当前节点的左右子树都不为空,则当前节点的深度等于左右子树深度的最小值加1。
// 这里加1是因为深度是从根节点开始计算的,根节点的深度是1。
int result = 1 + min(leftDepth, rightDepth);
return result;// 返回计算得到的深度结果。
}
// 定义名为minDepth的公共成员函数,用于返回二叉树的最小深度。
// 函数接受一个参数:指向二叉树根节点的指针root。
int minDepth(TreeNode* root) {
// 调用getDepth函数计算并返回整棵树的最小深度。
return getDepth(root);
}
};
// 二、二叉树的最小深度(迭代法)
class Solution2 {
public:
// 定义名为minDepth的公共成员函数,用于计算并返回二叉树的最小深度。
// 函数接受一个参数:指向二叉树根节点的指针root。
int minDepth(TreeNode* root) {
if (root == NULL) return 0;// 如果根节点为空,说明是一棵空树,返回深度0。
int depth = 0;// 初始化深度计数变量为0。
queue<TreeNode*> que;// 创建一个队列que,用于存储待访问的节点。
que.push(root);// 将根节点入队。
while (!que.empty()) {// 使用while循环进行遍历,直到队列为空。
int size = que.size(); // 获取队列中的节点数量。
depth++; // 增加深度计数,每遍历完一层,深度就增加1。
for (int i = 0; i < size; i++) {// 遍历当前层的所有节点。
TreeNode* node = que.front();// 取出队列前端的节点。
que.pop();// 将节点从队列中移除。
// 如果节点有左子节点,将其入队,以便后续遍历。
if (node->left) que.push(node->left);
// 如果节点有右子节点,将其入队,以便后续遍历。
if (node->right) que.push(node->right);
// 如果当前节点是叶子节点(即没有左右子节点),立即返回当前深度。
if (!node->left && !node->right) return depth;
}
}
// 如果遍历结束,返回记录的最大深度。
// 这个返回值在实际情况下不会被执行,因为所有叶子节点都会被提前返回。
return depth;
}
};
//测试
// 辅助函数,用于创建一个新的TreeNode
TreeNode* createNode(int value) {
return new TreeNode(value);
}
// 辅助函数,用于构建二叉树
TreeNode* buildTree(vector<int>& values) {
if (values.empty()) return NULL;
TreeNode* root = createNode(values[0]);
queue<TreeNode*> queueNode;
queueNode.push(root);
int i = 1;
while (!queueNode.empty()) {
TreeNode* node = queueNode.front();
queueNode.pop();
if (i < values.size()) {
node->left = createNode(values[i++]);
queueNode.push(node->left);
}
if (i < values.size()) {
node->right = createNode(values[i++]);
queueNode.push(node->right);
}
}
return root;
}
// 打印容器中的所有元素,用于验证测试结果
void printVector(const vector<int>& vec) {
for (int value : vec) {
cout << value << " ";
}
cout << endl;
}
// 主函数
int main() {
vector<int> treeValues = { 1,2,3,4,5, };// 定义二叉树的层序遍历结果,用于构建二叉树
TreeNode* root = buildTree(treeValues); // 构建二叉树
Solution1 s1;// 创建Solution类的实例
Solution2 s2;
int result1 = s1.minDepth(root);// 传入二叉树的根节点
int result2 = s2.minDepth(root);
cout << "二叉树的最小深度(递归法)是: " << result1 << endl;
cout << endl;
cout << "二叉树的最小深度(迭代法)是: " << result2 << endl;
cout << endl;
return 0;
}
三、完全二叉树的节点个数
1.题目
Leetcode:第 222 题
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2h
个节点。
示例 1:
输入:root = [1,2,3,4,5,6] 输出:6
示例 2:
输入:root = [] 输出:0
示例 3:
输入:root = [1] 输出:1
2.解题思路
使用递归法和迭代法遍历二叉树,计算二叉树的节点个数
3.实现代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// 定义一个结构体TreeNode,用于表示二叉树的节点。
struct TreeNode {
int val; // 存储节点的值。
TreeNode* left; // 指向该节点左子树的指针。
TreeNode* right; // 指向该节点右子树的指针。
// TreeNode的构造函数,用于创建一个TreeNode实例。
// 参数x是节点的值,left和right默认为NULL,表示没有左右子节点。
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
// 一、二叉树的节点个数(递归法)
class Solution1 {
public:
// 定义名为getNodesNum的辅助函数,用于递归地计算二叉树中节点的总数。
// 函数接受一个参数:指向二叉树节点的指针node。
int getNodesNum(TreeNode* node) {
if (node == NULL) return 0; // 如果传入的节点为空,说明是一棵空树,返回节点总数0。
int leftNum = getNodesNum(node->left);// 递归地计算左子树中节点的总数。
int rightNum = getNodesNum(node->right); // 递归地计算右子树中节点的总数。
int treeNum = 1 + leftNum + rightNum; // 计算当前树的节点总数,为左子树节点数、右子树节点数加上当前节点本身(1)。
return treeNum;// 返回计算得到的节点总数。
}
// 定义名为countNodes的公共成员函数,用于返回二叉树的节点总数。
// 函数接受一个参数:指向二叉树根节点的指针root。
int countNodes(TreeNode* root) {
return getNodesNum(root); // 调用getNodesNum函数计算并返回整棵树的节点总数。
}
};
// 一、二叉树的节点个数(迭代法)
class Solution2 {
public:
// 定义名为countNodes的成员函数,用于计算并返回二叉树的节点总数。
// 函数接受一个参数:指向二叉树根节点的指针root。
int countNodes(TreeNode* root) {
queue<TreeNode*> que; // 创建一个队列que,用于存储待访问的节点。
if (root != NULL) que.push(root); // 如果根节点不为空,则将其入队。
int result = 0;// 初始化节点计数变量为0。
while (!que.empty()) { // 使用while循环进行遍历,直到队列为空。
TreeNode* node = que.front();// 取出队列前端的节点。
que.pop();// 将节点从队列中移除。
result++;// 增加节点计数。
if (node->left) que.push(node->left); // 如果节点有左子节点,将其入队,以便后续遍历。
if (node->right) que.push(node->right);// 如果节点有右子节点,将其入队,以便后续遍历。
}
return result;// 返回计算得到的节点总数。
}
};
//测试
// 辅助函数,用于创建一个新的TreeNode
TreeNode* createNode(int value) {
return new TreeNode(value);
}
// 辅助函数,用于构建二叉树
TreeNode* buildTree(vector<int>& values) {
if (values.empty()) return NULL;
TreeNode* root = createNode(values[0]);
queue<TreeNode*> queueNode;
queueNode.push(root);
int i = 1;
while (!queueNode.empty()) {
TreeNode* node = queueNode.front();
queueNode.pop();
if (i < values.size()) {
node->left = createNode(values[i++]);
queueNode.push(node->left);
}
if (i < values.size()) {
node->right = createNode(values[i++]);
queueNode.push(node->right);
}
}
return root;
}
// 打印容器中的所有元素,用于验证测试结果
void printVector(const vector<int>& vec) {
for (int value : vec) {
cout << value << " ";
}
cout << endl;
}
// 主函数
int main() {
vector<int> treeValues = { 1, 2, 3, 4, 5, 6, 7 };// 定义二叉树的层序遍历结果,用于构建二叉树
TreeNode* root = buildTree(treeValues); // 构建二叉树
Solution1 s1;// 创建Solution类的实例
Solution2 s2;
int result1 = s1.countNodes(root);// 传入二叉树的根节点
int result2 = s2.countNodes(root);
cout << "二叉树的节点个数(递归法)是: " << result1 << endl;
cout << endl;
cout << "二叉树的节点个数(迭代法)是: " << result2 << endl;
cout << endl;
return 0;
}
ps:以上皆是本人在探索算法旅途中的浅薄见解,诚挚地希望得到各位的宝贵意见与悉心指导,若有不足或谬误之处,还请多多指教。