代码随想录算法训练营第十六天_第六章_二叉树 | 104.二叉树的最大深度 559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

文章介绍了如何使用递归和迭代方法计算二叉树的最大深度和最小深度,包括后序和前序遍历的策略。同时,对于完全二叉树,文章提供了计算节点数量的方法,特别关注满二叉树的情况。

LeetCode 104.二叉树的最大深度

⭐高度👆 vs 深度👇:

  • 二叉树节点的高度👆(后序):指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
  • 二叉树节点的深度👇(前序):指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)

视频讲解https://www.bilibili.com/video/BV1Gd4y1V75u/?vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解https://programmercarl.com/0104.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%A4%A7%E6%B7%B1%E5%BA%A6.html

根节点的高度就是二叉树的最大深度

  • 思路:
    • 通过后序求根节点的高度:(父节点高度 = 子节点高度 + 1)
    1. 确定递归函数的参数和返回值:根节点        int
    2. 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
    3. 确定单层递归的逻辑:先求它的左子树的高度,再求右子树的高度,最后左右子树高度取大 再+1 (加1是因为算上当前中间节点)就是当前子树的高度。
    • 通过前序求根节点的深度:(子节点深度 = 父节点深度 + 1)
    1. 确定递归函数的参数和返回值:(Treenode* node, int depth)        void
    2. 确定终止条件:如果为叶子节点的话,就返回。
    3. 确定单层递归的逻辑:左孩子非空,则求左孩子深度;右孩子非空,则求右孩子深度。父节点深度为 depth,故 depth + 1 就是当前节点的深度。
  • 代码: 
// 后序
class solution {
public:
    int getdepth(Treenode* node) {
        if (node == NULL) return 0;
        int leftdepth = getdepth(node->left);       // 左
        int rightdepth = getdepth(node->right);     // 右
        int depth = 1 + max(leftdepth, rightdepth); // 中
        return depth;
    }
    int maxdepth(Treenode* root) {
        return getdepth(root);
    }
};
// 后序:精简版
class solution {
public:
    int maxdepth(Treenode* root) {
        if (root == null) return 0;
        return 1 + max(maxdepth(root->left), maxdepth(root->right));
    }
};
// 前序
class solution {
public:
    int result;
    void getdepth(Treenode* node, int depth) {
        result = depth > result ? depth : result; // 中

        if (node->left == NULL && node->right == NULL) return ;

        if (node->left) { // 左
            depth++;    // 深度+1
            getdepth(node->left, depth);
            depth--;    // 回溯,深度-1
        }
        if (node->right) { // 右
            depth++;    // 深度+1
            getdepth(node->right, depth);
            depth--;    // 回溯,深度-1
        }
        return ;
    }
    int maxdepth(Treenode* root) {
        result = 0;
        if (root == NULL) return result;
        getdepth(root, 1);
        return result;
    }
};
// 前序:精简版
class solution {
public:
    int result;
    // node为当前处理节点(非空),depth为node的深度
    void getdepth(Treenode* node, int depth) {
        result = depth > result ? depth : result; // 中
        if (node->left == NULL && node->right == NULL) return ;
        if (node->left) { // 左
            getdepth(node->left, depth + 1);
        }
        if (node->right) { // 右
            getdepth(node->right, depth + 1);
        }
        return ;
    }
    int maxdepth(Treenode* root) {
        result = 0;
        if (root == 0) return result;
        // 根节点(非空)深度为1
        getdepth(root, 1);
        return result;
    }
};
// 迭代:层序
class solution {
public:
    int maxdepth(Treenode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<Treenode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size();
            depth++; // 记录深度
            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;
    }
};

 相关题目:

LeetCode 559.n叉树的最大深度

// 递归法(后序)
class solution {
public:
    int maxdepth(node* root) {
        if (root == 0) return 0;
        int depth = 0;
        for (int i = 0; i < root->children.size(); i++) {
            depth = max (depth, maxdepth(root->children[i]));
        }
        return depth + 1;
    }
};
// 前序
class Solution {
public:
    int result;
    // depth为node父节点的深度
    void getHeight(Node* node, int depth) {
        if (node == NULL) return;
        // node深度:depth + 1
        result = (depth + 1) > result ? (depth + 1) : result;
        for (int i = 0; i < node->children.size(); ++i) {
            getHeight(node->children[i], depth + 1);
        }
    }
    int maxDepth(Node* root) {
        result = 0;
        getHeight(root, 0);
        return result;
    }
};
// 迭代法(层序)
class solution {
public:
    int maxdepth(node* root) {
        queue<node*> que;
        if (root != NULL) que.push(root);
        int depth = 0;
        while (!que.empty()) {
            int size = que.size();
            depth++; // 记录深度
            for (int i = 0; i < size; i++) {
                node* node = que.front();
                que.pop();
                for (int j = 0; j < node->children.size(); j++) {
                    if (node->children[j]) que.push(node->children[j]);
                }
            }
        }
        return depth;
    }
};

LeetCode 111.二叉树的最小深度

        最小深度是从根节点到最近叶子节点的最短路径上的节点数量 

视频讲解https://www.bilibili.com/video/BV1QD4y1B7e2文章讲解https://programmercarl.com/0111.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E6%B7%B1%E5%BA%A6.html#%E9%80%92%E5%BD%92%E6%B3%95

111.二叉树的最小深度

  • 思路:根节点到叶子节点的最小距离
    • 后序:左右子树高度取小 → 以中节点为子树的最小深度?
    1. 递归函数参数、返回值:(Treenode* node)        返回值 int
    2. 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
    3. 确定单层递归的逻辑:(若子树一空一非空,返回非空子树最小深度 +1)先求它的左子树的最小深度,再求右子树的最小深度,最后左右子树最小深度取小 再+1 (加1是因为算上当前中间节点)就是当前子树的最小深度。
    • 前序:
    1. 确定递归函数的参数和返回值:(Treenode* node, int depth)        void
    2. 确定终止条件:如果为叶子节点的话,记录结果,返回。
    3. 确定单层递归的逻辑:左孩子非空,则求左孩子最小深度;右孩子非空,则求右孩子最小深度。父节点深度为 depth,故 depth + 1 就是当前节点的深度。
  • 代码:
// 后序
class Solution {
public:
    int getDepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftDepth = getDepth(node->left);           // 左
        int rightDepth = getDepth(node->right);         // 右
                                                        // 中
        // 当一个左子树为空,右不为空,这时并不是最低点
        if (node->left == NULL && node->right != NULL) { 
            return 1 + rightDepth;
        }   
        // 当一个右子树为空,左不为空,这时并不是最低点
        if (node->left != NULL && node->right == NULL) { 
            return 1 + leftDepth;
        }
        int result = 1 + min(leftDepth, rightDepth);
        return result;
    }

    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};
// 后序:精简版
class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        if (root->left == NULL && root->right != NULL) {
            return 1 + minDepth(root->right);
        }
        if (root->left != NULL && root->right == NULL) {
            return 1 + minDepth(root->left);
        }
        return 1 + min(minDepth(root->left), minDepth(root->right));
    }
};
// 前序
class Solution {
private:
    int result;
    void getdepth(TreeNode* node, int depth) {
        if (node->left == NULL && node->right == NULL) {
            result = min(depth, result);  
            return;
        }
        // 中 只不过中没有处理的逻辑
        if (node->left) { // 左
            getdepth(node->left, depth + 1);
        }
        if (node->right) { // 右
            getdepth(node->right, depth + 1);
        }
        return ;
    }

public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        result = INT_MAX;
        getdepth(root, 1);
        return result;
    }
};
// 迭代:层序
class Solution {
public:

    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size();
            depth++; // 记录最小深度
            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;
    }
};

LeetCode 222.完全二叉树的节点个数

⭐完全二叉树:找满二叉树,利用公式计算节点个数:2^深度 - 1
视频讲解https://www.bilibili.com/video/BV1eW4y1B7pD文章讲解https://programmercarl.com/0222.%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%8A%82%E7%82%B9%E4%B8%AA%E6%95%B0.html

  • 思路:
    • 普通二叉树:左子树节点个数 + 右子树节点个数 + 1        时间复杂度:O(n)
    • 完全二叉树:前序遍历找构成满二叉树的子树

222.完全二叉树的节点个数

前提:完全二叉树,每层从左到右节点连续,故可以直接判断两侧节点数,若相等则为满二叉树

  1. 参数、返回值:
  2. 终止条件:
    if (root == nullptr) return 0; 
    // 开始根据左深度和右深度是否相同来判断该子树是不是满二叉树
    TreeNode* left = root->left;
    TreeNode* right = root->right;
    int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
    while (left) {  // 求左子树深度
        left = left->left;
        leftDepth++;
    }
    while (right) { // 求右子树深度
        right = right->right;
        rightDepth++;
    }
    if (leftDepth == rightDepth) {
        return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,返回满足满二叉树的子树节点数量
    }
  3. 单层递归逻辑:左子树节点个数 + 右子树节点个数 + 1
  • 代码:
// 适用于普通二叉树
// 递归
class Solution {
private:
    int getNodesNum(TreeNode* cur) {
        if (cur == NULL) 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);
    }
};
// 递归:精简版
class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == NULL) return 0;
        return 1 + countNodes(root->left) + countNodes(root->right);
    }
};

// 迭代
class Solution {
public:
    int countNodes(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) 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;
    }
};
// 适用于完全二叉树
class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr) return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
        while (left) {  // 求左子树深度
            left = left->left;
            leftDepth++;
        }
        while (right) { // 求右子树深度
            right = right->right;
            rightDepth++;
        }
        if (leftDepth == rightDepth) {
            return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
        }
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};

注:2 << i - 1        2 左移 i - 1 位,相当于 2 * 2 * ... * 2        i - 1 个 2

即 2 ^ i 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值