Leetcode算法训练日记 | day16

一、二叉树的最大深度

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:以上皆是本人在探索算法旅途中的浅薄见解,诚挚地希望得到各位的宝贵意见与悉心指导,若有不足或谬误之处,还请多多指教。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值