求二叉树中以x为根的子树的深度_还在玩耍的你,该总结啦!(本周小结之二叉树)...

a302985c8f328eb22a96c6dc147a39a2.gif给「代码随想录」一个星标吧!

有学习就要有总结

本周小结

本周赶上了十一国庆,估计大家已经对本周末没什么概念了,但是我们该做总结还是要做总结的。

本周的主题其实是「简单但并不简单」,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简答题目其实里面都藏了很多细节。这些细节我都给大家展现了出来。

周一

本周刚开始我们讲解了判断二叉树是否对称的写法, 二叉树:我对称么?。

这道题目的本质是要比较两个树(这两个树是根节点的左右子树),遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。

而本题的迭代法中我们使用了队列,需要注意的是这不是层序遍历,而且仅仅通过一个容器来成对的存放我们要比较的元素,认识到这一点之后就发现:用队列,用栈,甚至用数组,都是可以的。

那么做完本题之后,再看如下两个题目。

  • 100.相同的树
  • 572.另一个树的子树

「二叉树:我对称么?中的递归法和迭代法只需要稍作修改其中一个树的遍历顺序,便可刷了100.相同的树。」

100.相同的树的递归代码如下:

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);
    }
};

100.相同的树,精简之后代码如下:

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;
        else return compare(left->left, right->left) && compare(left->right, right->right);

    }
    bool isSameTree(TreeNode* p, TreeNode* q) {
        return compare(p, q);
    }
};

100.相同的树,迭代法代码如下:

lass Solution {
public:

    bool isSameTree(TreeNode* p, TreeNode* q) {
        if (p == NULL && q == NULL) return true;
        if (p == NULL || q == NULL) return false;
        queue que;
        que.push(p);   
        que.push(q);  while (!que.empty()) {  
            TreeNode* leftNode = que.front(); que.pop();
            TreeNode* rightNode = que.front(); que.pop();if (!leftNode && !rightNode) {  continue;
            }if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {return false;
            }
            // 相对于求对称二叉树,这里两个树都要保持一样的遍历顺序
            que.push(leftNode->left); 
            que.push(rightNode->left); 
            que.push(leftNode->right);  
            que.push(rightNode->right);  
        }return true;
    }
};

而572.另一个树的子树,则和 100.相同的树几乎一样的了,大家可以直接AC了。

周二

在二叉树:看看这些树的最大深度中,我们讲解了如何求二叉树的最大深度。

本题可以使用前序,也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序呢求的是高度。

「而根节点的高度就是二叉树的最大深度」,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度,所以二叉树:看看这些树的最大深度中使用的是后序遍历。

本题当然也可以使用前序,代码如下:(「充分表现出求深度回溯的过程」)

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 == 0) return result;
        getDepth(root, 1);
        return result;
    }
};

「可以看出使用了前序(中左右)的遍历顺序,这才是真正求深度的逻辑!」

注意以上代码是为了把细节体现出来,简化一下代码如下:

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) { // 左
            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;
        getDepth(root, 1);
        return result;
    }
};

周三

在二叉树:看看这些树的最小深度中,我们讲解如何求二叉树的最小深度, 这道题目要是稍不留心很容易犯错。

「注意这里最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点。」

什么是叶子节点,左右孩子都为空的节点才是叶子节点!

「求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。」

注意到这一点之后 递归法和迭代法 都可以参照二叉树:看看这些树的最大深度写出来。

周四

我们在二叉树:我有多少个节点?中,讲解了如何求二叉树的节点数量。

这一天是十一长假的第一天,又是双节,所以简单一些,只要把之前两篇二叉树:看看这些树的最大深度, 二叉树:看看这些树的最小深度都认真看了的话,这道题目可以分分钟刷掉了。

估计此时大家对这一类求二叉树节点数量以及求深度应该非常熟练了。

周五

在二叉树:我平衡么?中讲解了如何判断二叉树是否是平衡二叉树

今天讲解一道判断平衡二叉树的题目,其实 方法上我们之前讲解深度的时候都讲过了,但是这次我们通过这道题目彻底搞清楚二叉树高度与深度的问题,以及对应的遍历方式。

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。

「但leetcode中强调的深度和高度很明显是按照节点来计算的」

关于根节点的深度究竟是1 还是 0,不同的地方有不一样的标准,leetcode的题目中都是以节点为一度,即根节点深度是1。但维基百科上定义用边为一度,即根节点的深度是0,我们暂时以leetcode为准(毕竟要在这上面刷题)。

当然此题用迭代法,其实效率很低,因为没有很好的模拟回溯的过程,所以迭代法有很多重复的计算。

虽然理论上所有的递归都可以用迭代来实现,但是有的场景难度可能比较大。

「例如:都知道回溯法其实就是递归,但是很少人用迭代的方式去实现回溯算法!」

讲了这么多二叉树题目的迭代法,有的同学会疑惑,迭代法中究竟什么时候用队列,什么时候用栈?

「如果是模拟前中后序遍历就用栈,如果是适合层序遍历就用队列,当然还是其他情况,那么就是 先用队列试试行不行,不行就用栈。」

周六

在二叉树:找我的所有路径?中正式涉及到了回溯,很多同学过了这道题目,可能都不知道自己使用了回溯,其实回溯和递归都是相伴相生的。最后我依然给出了迭代法的版本。

我在题解中第一个版本的代码会把回溯的过程充分体现出来,如果大家直接看简洁的代码版本,很可能就会忽略的回溯的存在。

我在文中也强调了这一点。

有的同学还不理解 ,文中精简之后的递归代码,回溯究竟隐藏在哪里了。

文中我明确的说了:「回溯就隐藏在traversal(cur->left, path + "->", result);中的 path + "->"。每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。」

如果还不理解的话,可以把

traversal(cur->left, path + "->", result);

改成

string tmp = path + "->";
traversal(cur->left, tmp, result);

看看还行不行了,答案是这么写就不行了,因为没有回溯了。

总结

二叉树的题目,我都是使用了递归三部曲一步一步的把整个过程分析出来,而不是上来就给出简洁的代码。

一些同学可能上来就能写出代码,大体上也知道是为啥,可以自圆其说,但往细节一扣,就不知道了。

所以刚接触二叉树的同学,建议按照文章分析的步骤一步一步来,不要上来就照着精简的代码写(那样写完了也很容易忘的,知其然不知其所以然)。

「简短的代码看不出遍历的顺序,也看不出分析的逻辑,还会把必要的回溯的逻辑隐藏了,所以尽量按照原理分析一步一步来,写出来之后,再去优化代码。」

下周依然是二叉树,大家加个油!!

在留言区留下你的思路吧!

-------end-------

我将算法学习相关的资料已经整理到了Github :https://github.com/youngyangyang04/leetcode-master,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图看一看一定会有所收获,如果给你有帮助给一个star支持一下吧!

另外因为公众号改版,时间线被打乱,一些精彩文章大家可能错过了。如果感觉这里的文章对你有帮助,赶紧给「代码随想录」加一个星标吧,方便第一时间阅读文章往期精彩回顾二叉树:找我的所有路径?二叉树:我平衡么?二叉树:我有多少个节点?二叉树:看看这些树的最小深度二叉树:看看这些树的最大深度二叉树:我对称么?本周小结!(二叉树)二叉树:你真的会翻转二叉树么?二叉树:层序遍历登场!二叉树:前中后序迭代方式的写法就不能统一一下么?二叉树:听说递归能做的,栈也能做!二叉树:一入递归深似海,从此offer是路人关于二叉树,你该了解这些!「代码随想录」期待你的关注!

每天8:35准时推送一道经典算法题目,推送的每道题目都不是孤立的,而是由浅入深,环环相扣,帮你梳理算法知识脉络,轻松学算法!

05b0e5ca5cd0fd2deff2c4c3042190d2.png9c2243cd3bfbd727993c9c7a6988c665.png刷题可以加我微信!右边为个人微信,添加时备注:「简单自我介绍」+「组队刷题」我就知道你[在看]61019d5c71531317ce04942e89eec1ef.gif

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle (+)的可读性,Oracle基础笔记一

1.基本 SELECT 语句1.基本 SELECT 语句SELECT 标识 选择哪些列。FROM 标识从哪个表中选择。注意:SQL 语言大小写不敏感。SQL 可以写在一行或者多行关键字不能被缩写也不能分行各子句一般要分行写。使用缩进提高语句的可读性。2.算术运算符( - * /)数字和日期使…

钉钉功能介绍_平棉集团组织召开阿里钉钉办公系统基础功能培训会

4月11日上午,平棉集团在总部26楼多媒体会议室组织召开阿里钉钉办公系统基础功能培训会,邀请河南一一信息技术公司经理杨杉前来授课。集团公司董事长张先顺及公司领导陈亚民、王仲山、王向阳、陶尚林,各生产经营单位主管销售工作的负责人和公司…

qemu搭建arm运行linux内核,centos使用qemu搭建ARM64运行环境

准备工作(1) linux 内核源码, 从github上获取git clone https://github.com/torvalds/linuxmake kernelversion(2) 交叉编译工具,从linaro官网(www.linaro.org)上获取解压后设置环境变量即可xz -d gcc-linaro-xxx.tar.xztar -xvf gcc-linaro-xxx.tarexpo…

java 某年某月中第几周 开始时间和结束时间_重磅!库里又要签下一超级大合同!4年2亿啊!退役时间也定了...

好家伙!现在的超级巨星都喜欢提前续约了,继詹姆斯与湖人签下两年8500万美元顶薪协议后,库里也有望达成这一成就。当地时间周一训练结束后,他接受采访谈到自己的续约问题,表示已经和球队交流过,同时明确表态…

vb ftp linux,VB FTP上传和下载模块

Option ExplicitPrivate Const INTERNET_OPEN_TYPE_DIRECT 1Private Const scuseragent "vb wininet"Private Const INTERNET_FLAG_PASSIVE &H8000000调用设置环境Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOp…

python struct pack一个数组_Python中struct.pack的一个疑问

展开全部的确很奇怪。我试验了10几分钟,你按下面的方法来做就可以正确。import structzzz ("{Type:2}").encode("utf-8")length len(zzz)a struct.pack("%ds"%length,zzz)print(a)简单的说32313133353236313431303231363533e59b9e…

linux list 添加失败,linux运维实战案例之Argument list too long错误与解决方法

1、错误现象这是一台Mysql数据库服务器,在系统中运行了很多定时任务,今天通过crontab命令又添加了一个计划任务,退出时发生了如下报错:#crontab -e编辑完成后,保存退出,就出现下面如下图所示错误&#xff1…

软件项目周报模板_一份高质量的职场工作周报,要这样写

周报是会呼吸的痛,它会在每个周五来回滚动。几乎每个职场人都会为周报所折腰,因为周报看起来是小事,但又不仅仅是小事。周报,是职场人士对一周工作的总结和记录,是展示自己工作状态和成果的重要载体,是领导…

linux 多线程客户端服务端通信,[转载]多线程实现服务器和客户端、客户端和客户端通信;需要代码,留言...

一、实验名称动手打造自己的 IM二、实验目的1本次实验旨在锻炼大家的Socket编程能力,以日常生活中广泛使用的IM软件为背景,培养大家对于网络编程的兴趣。2、通过本次实验,培养linux环境下网络编程能力,使得我们对网络应用层的网络…

python安装sqap_python文件I/O

python文件I/O键盘读入:raw_input函数str raw_input("请输入: ")input函数,可以接受一个python表达式作为输入str input("请输入:")输入:[ x*5 for x in range(2, 10, 2)]open函数:f…

linux 设置ssh并发度,在linux如何使用ControlPersist加快SSH连接速度的问题

不经意间我们又来到了文章的学习,在众多学习中,我们的文章也许不起眼,但是想必大家都有很多问题吧,所以重要的下面我们就来讲解一下,大家一定要认真看奥!!Linux系统进行服务器配置管理迁移的时候…

linux下c标准库位置,C 标准库 IO 使用详解

其实输入与输出对于不管什么系统的设计都是异常重要的,比如设计 C 接口函数,首先要设计好输入参数、输出参数和返回值,接下来才能开始设计具体的实现过程。C 语言标准库提供的接口功能很有限,不像 Python 库。不过想把它用好也不容…

python调用系统_python 执行系统命令

Python中执行系统命令常见的几种方法:(1)os.system# 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息# 如果再命令行下执行,结果直接打印出来例如:>>> import os>>> os.system(ls)chk_err_log.py…

linux libbz2.so.1,libbz2.so.1.0: cannot open shared object file: No such file or directory

在解决这个报错的过程中,我学到了Linux下解决问题的一种新思路。这个报错很早之前就遇到过,当时是用自己安装的miniconda来下载安装samtools(非root用户),安装完成之后运行就这样报错了,但是其他的软件又可以正常运行,…

python文件对象是可以迭代的_详解python可迭代对象、迭代器和生成器

可迭代对象什么是可迭代对象?顾名思义就是可以迭代的一个对象,再通俗点就是可以被for循环遍历的对象,如常用的list、str等数据类型。我们可以使用isinstance来判断这个数据是否是可迭代对象,在此要先从Iterable包中导入模块collec…

linux更改nginx最大访问数,Linux下nginx服务的配置文件nginx.conf中模块的讲解之配置limit_conn_zone来限制并发连接数以及下载速率...

一、限制并发连接数的配置方法如下:1、在nginx.conf里的http{}里加上如下代码:# vim /usr/local/nginx/conf/nginx.conf#在其中的36行加入下面的内容(在http{}模块中加入的)limit_conn_zone $binary_remote_addr zoneaddr:10m;#解释内容如下:要限制连接&…

python实现杨辉三角形博客园_Python实现杨辉三角

杨辉三角,是二项式系数在三角形中的一种几何排列。在欧洲,这个表叫做帕斯卡三角形。帕斯卡(1623----1662)是在1654年发现这一规律的,比杨辉要迟393年,比贾宪迟600年。杨辉三角是中国古代数学的杰出研究成果之一,它把二…

ftm模块linux驱动,飞思卡尔k系列_ftm模块详解.doc

飞思卡尔k系列_ftm模块详解1.5FTM模块1.5.1 FTM模块简介FTM模块是一个多功能定时器模块,主要功能有,PWM输出、输入捕捉、输出比较、定时中断、脉冲加减计数、脉冲周期脉宽测量。在K10中,共有FTM0,FTM1,FTM2三个独立的F…

python列表切片图解_Python列表切片操作实例总结

本文实例讲述了Python列表切片操作。分享给大家供大家参考,具体如下:切片指的是列表的一部分。1 基本用法指定第一个元素和最后一个元素的索引,即可创建切片 。Python 会在到达指定的第二个索引之前元素后停止 。books[半生缘,往事并不如烟,心…

乱码 讯飞 语音识别_一段讯飞、百度等语音识别API无法识别的语音最终解决办法...

最近在做语音识别、字幕扒词相关的工作,遇到了一段录音(https://download.csdn.net/download/u014220286/12169183,各位有兴趣的可以下载下来试试),音质什么的和其他处理过的无二异,也是普通话,照常理说应该能识别出来…