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

目录

Leetcode 104.二叉树的最大深度

Leetcode 559.n叉树的最大深度

Leetcode 111.二叉树的最小深度

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


Leetcode 104.二叉树的最大深度

题目链接:Leetcode 104.二叉树的最大深度

题目描述:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

思路:前序遍历通常用于求深度,后序遍历通常用于求高度。这么来看这道题似乎只能用前序遍历了,不过我们知道根节点的高度就是二叉树的最大深度,因此两种遍历方式都可以。除此之外,层序遍历对于本题也是适合的,我们只需要基于层序遍历的模板,添加统计层数的行为就可以了。

代码如下:(递归法——前序遍历)

class Solution {
public:
    int result;
    void getdepth(TreeNode* node, int depth) {
        result = max(result, depth);
        if (node->left == nullptr && node->right == nullptr)//中
            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 == nullptr)
            return result;
        getdepth(root, 1);
        return result;
    }
};

(递归法——后序遍历)

class Solution {
public:
    int getdepth(TreeNode* root) {
        if (root == nullptr)
            return 0;
        int leftdepth = getdepth(root->left);
        int rightdepth = getdepth(root->right);
        //这里加1是因为要算上当前中间节点那一层
        int depth = 1 + max(leftdepth, rightdepth);
        return depth;
    }
    int maxDepth(TreeNode* root) { return getdepth(root); }
};

(迭代法——层序遍历)

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == nullptr)
            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叉树的最大深度

题目链接:Leetcode 559.n叉树的最大深度

题目描述:给定一个 n 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

思路:这道题和上道题Leetcode 104.二叉树的最大深度几乎没什么区别,两道题的关键在于理解根节点的高度等于n叉树的最大深度。

代码如下:(递归法)

class Solution {
public:
    int maxDepth(Node* root) {
        if (root == nullptr)
            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 maxDepth(Node* root) {
        queue<Node*> que;
        int depth = 0;
        if (root != nullptr)
            que.push(root);
        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.二叉树的最小深度

题目链接:Leetcode 111.二叉树的最小深度

题目描述:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

思路:本题依然是前序遍历和后序遍历都可以,前序求的是深度,后序求的是高度。但一定要注意题干对最小深度的描述:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。什么是叶子节点左右孩子都为空的时候才是。如果左右孩子中只有一个孩子为空,则找深度时返回非空孩子的深度+1(而不是看最小深度);如果左右孩子都为空,说明是叶子节点,返回左右孩子的最小深度+1。

注:上述图片来源于《代码随想录》

代码如下:(递归法——前序遍历)

class Solution {
public:
    int result;
    void getDepth(TreeNode* node, int depth) {
        if (node == nullptr)
            return;
        //中,判断是否是叶子节点
        if (node->left == nullptr && node->right == nullptr) {
            result = min(result, depth);
        }
        if (node->left) {//左
            getDepth(node->left, depth + 1);
        }
        if (node->right) {//右
            getDepth(node->right, depth + 1);
        }
        return;
    }
    int minDepth(TreeNode* root) {
        if (root == nullptr)
            return 0;
        result=INT_MAX;
        getDepth(root, 1);
        return result;
    }
};

(递归法——后序遍历)

class Solution {
public:
    int getDepth(TreeNode* node) {
        if (node == nullptr)
            return 0;
        int leftdepth = getDepth(node->left);   //左
        int rightdepth = getDepth(node->right); //右
                                                //中
        if (node->left == nullptr && node->right != nullptr) {
            return 1 + rightdepth;
        }
        if (node->right == nullptr && node->left != nullptr) {
            return 1 + leftdepth;
        }
        return 1 + min(leftdepth, rightdepth);
    }
    int minDepth(TreeNode* root) { return getDepth(root); }
};

(迭代法——层序遍历)

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == nullptr)
            return 0;
        queue<TreeNode*> que;
        int depth = 0;
        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.完全二叉树的节点个数

题目链接:Leetcode 222.完全二叉树的节点个数

题目描述:给出一个完全二叉树,求出该树的节点个数。

思路:统计节点个数,遍历计数就好了,很容易解决本题。

代码如下:(递归法)

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr)
            return 0;
        int leftnum = countNodes(root->left);
        int rightnum = countNodes(root->right);
        int result = leftnum + rightnum + 1;
        return result;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(log n)

(迭代法)

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr)
            return 0;
        queue<TreeNode*> que;
        que.push(root);
        int result = 0;
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                result++;
                TreeNode* node = que.front();
                que.pop();
                if (node->left)
                    que.push(node->left);
                if (node->right)
                    que.push(node->right);
            }
        }
        return result;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

不过观察到题目给的是完全二叉树,因此可以利用它的性质来优化。在此之前需要了解完全二叉树和满二叉树的概念:可以看这里。在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1)  个节点。

完全二叉树只有两种情况,(1)就是满二叉树(2)最后一层叶子节点没有满。

对于(1),可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。

对于(2),分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。

接下来思考如何判断是否是满二叉树?在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。因此只需要递归判断一个节点的左右孩子深度是否相等就好了。

代码如下:(利用完全二叉树的性质优化)

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr)
            return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftdepth = 1, rightdepth = 1;//一个节点深度为1,
        while (left) {
            left = left->left;
            leftdepth++;
        }
        while (right) {
            right = right->right;
            rightdepth++;
        }
        if (leftdepth == rightdepth) {
            return pow(2, leftdepth) - 1;
        }
        return countNodes(root->left) + countNodes(root->right) + 1;//递归调用下一层
    }
};
  • 时间复杂度:O(log n × log n)
  • 空间复杂度:O(log n)

总结:做了这些有关二叉树的题,发现很多都是基于二叉树的遍历模板稍加修改就可以解决的题目,因此打牢基础很重要!

最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/352724.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【驱动系列】C#获取电脑硬件显卡核心代号信息

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《驱动系列》文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点…

Python笔记12-多线程、网络编程、正则表达式

文章目录 多线程网络编程正则表达式 多线程 现代操作系统比如Mac OS X&#xff0c;UNIX&#xff0c;Linux&#xff0c;Windows等&#xff0c;都是支持“多任务”的操作系统。 进程&#xff1a; 就是一个程序&#xff0c;运行在系统之上&#xff0c;那么便称之这个程序为一个运…

Linux进程间通信(IPC)机制之一:管道(Pipes)详解

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;Nonsense—Sabrina Carpenter 0:50━━━━━━️&#x1f49f;──────── 2:43 &#x1f504; ◀️ ⏸ ▶️ …

关于session每次请求都会改变的问题

这几天在部署一个前后端分离的项目&#xff0c;使用docker进行部署&#xff0c;在本地测试没有一点问题没有&#xff0c;前脚刚把后端部署到服务器&#xff0c;后脚测试就出现了问题&#xff01;查看控制台报错提示跨域错误&#xff1f;但是对于静态资源请求&#xff0c;包括登…

数据结构.线性表

1.静态分配 #include<iostream> using namespace std; const int N 10; typedef struct {int data[N];int length;}SqList; void InitList(SqList &L) {for (int i 0; i < N; i){L.data[i] 0;}L.length 0; }int main() {SqList L;InitList(L);return 0; }2.动…

2024年AI全景预测

欢迎来到 2024 年人工智能和技术的可能性之旅。 在这里&#xff0c;每一个预测都是一个潜在的窗口&#xff0c;通向充满创新、变革、更重要的是类似于 1950 年代工业革命的未来。 20 世纪 50 年代见证了数字计算的兴起&#xff0c;重塑了行业和社会规范。 如今&#xff0c;人工…

运行adprep /forestprep扩展Active Directory架构

运行 adprep /forestprep 是为了扩展Active Directory架构&#xff0c;以便为整个林添加新版本Windows Server所支持的新类、属性和其他目录对象。在升级到更高版本的Windows Server并提升林功能级别之前&#xff0c;通常需要执行此操作。 以下是详细步骤&#xff1a; 确认环境…

flask框架制作前端网页作为GUI

一、语法和原理 &#xff08;一&#xff09;、文件目录结构 需要注意的问题&#xff1a;启动文件命名必须是app.py。 一个典型的Flask应用通常包含以下几个基本文件和文件夹&#xff1a; app.py&#xff1a;应用的入口文件&#xff0c;包含了应用的初始化和配置。 requirem…

【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]

阅读导航 引言一、特殊类 --- 不能被拷贝的类1. C98方式&#xff1a;2. C11方式&#xff1a; 二、特殊类 --- 只能在堆上创建对象的类三、特殊类 --- 只能在栈上创建对象的类四、特殊类 --- 不能被继承的类1. C98方式2. C11方法 总结温馨提示 引言 在面向对象编程中&#xff0…

Nginx与keepalived实现集群

提醒一下&#xff1a;下面实例讲解是在mac虚拟机里的Ubuntu系统演示的&#xff1b; Nginx与keepalived实现集群实现的效果 两台服务器都安装Nginx与keepalived&#xff1a; master服务器的ip(192.168.200.2) backup服务器的ip(192.168.200.4) 将 master服务器Nginx与keepalive…

【Mybatis的一二级缓存】

缓存是什么&#xff1f; 缓存其实就是存储在内存中的临时数据&#xff0c;这里的数据量会比较小&#xff0c;一般来说&#xff0c;服务器的内存也是有限的&#xff0c;不可能将所有的数据都放到服务器的内存里面&#xff0c;所以&#xff0c; 只会把关键数据放到缓存中&#x…

C# 命名管道NamedPipeServerStream使用

NamedPipeServerStream 是 .NET Framework 和 .NET Core 中提供的一个类&#xff0c;用于创建和操作命名管道的服务器端。命名管道是一种在同一台计算机上或不同计算机之间进行进程间通信的机制。 命名管道允许两个或多个进程通过共享的管道进行通信。其中一个进程充当服务器&…

RNN预测下一句文本简单示例

根据句子前半句的内容推理出后半部分的内容&#xff0c;这样的任务可以使用循环的方式来实现。 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种用于处理序列数据的强大神经网络模型。与传统的前馈神经网络不同&#xff0c;RNN能够通过其…

独享http代理安全性是更高的吗?

不同于共享代理&#xff0c;独享代理IP为单一用户提供专用的IP&#xff0c;带来了一系列需要考虑的问题。今天我们就一起来看看独享代理IP的优势&#xff0c;到底在哪里。 我们得先来看看什么是代理IP。简单来说&#xff0c;代理服务器充当客户机和互联网之间的中间人。当你使用…

C/C++ - 面向对象编程

面向对象 面向过程编程&#xff1a; 数据和函数分离&#xff1a;在C语言中&#xff0c;数据和函数是分开定义和操作的。数据是通过全局变量或传递给函数的参数来传递的&#xff0c;函数则独立于数据。函数为主导&#xff1a;C语言以函数为主导&#xff0c;程序的执行流程由函数…

复式记账的概念特点和记账规则

目录 一. 复式记账法二. 借贷记账法三. 借贷记账法的记账规则四. 复试记账法应用举例4.1 三栏式账户举例4.2 T型账户记录举例4.3 记账规则验证举例 \quad 一. 复式记账法 \quad 复式记账法是指对于任何一笔经济业务都要用相等的金额&#xff0c;在两个或两个以上的有关账户中进…

GIT使用,看它就够了

一、目的 Git的熟练使用是一个加分项&#xff0c;本文将对常用的Git命令做一个基本介绍&#xff0c;看了本篇文章&#xff0c;再也不会因为不会使用git而被嘲笑了。 二、设置与配置 在第一次调用Git到日常的微调和参考&#xff0c;用得最多的就是config和help命令。 2.1 gi…

4核16G幻兽帕鲁服务器性能测评,真牛

腾讯云幻兽帕鲁服务器4核16G14M配置&#xff0c;14M公网带宽&#xff0c;限制2500GB月流量&#xff0c;系统盘为220GB SSD盘&#xff0c;优惠价格66元1个月&#xff0c;277元3个月&#xff0c;支持4到8个玩家畅玩&#xff0c;地域可选择上海/北京/成都/南京/广州&#xff0c;腾…

第十六章 Spring cloud stream应用

文章目录 前言1、stream设计思想2、编码常用的注解3、编码步骤3.1、添加依赖3.2、修改配置文件3.3、生产3.4、消费3.5、延迟队列3.5.1、修改配置文件3.5.2、生产端3.5.2、消息确认机制 消费端 前言 https://github.com/spring-cloud/spring-cloud-stream-binder-rabbit 官方定…

GPT-SoVITS 本地搭建踩坑

GPT-SoVITS 本地搭建踩坑 前言搭建下载解压VSCode打开安装依赖包修改内容1.重新安装版本2.修改文件内容 运行总结 前言 传言GPT-SoVITS作为当前与BertVits2.3并列的TTS大模型&#xff0c;于是本地搭了一个&#xff0c;简单说一下坑。 搭建 下载 到GitHub点击此处下载 http…