有读者反馈,现在谁不是为了找工作才学的数据结构,确实很有道理,是我肤浅了。所以为了满足大家的需求,这里总结下LeetCode里的数据结构。对于我们这种职场老人来说,刷LeetCode会遇到个很尴尬的问题,就是每道题看起来都很熟悉,都觉得是十拿九稳了,但是真要你写出来,又很容易卡壳。如果人家让你写个反转链表的题目都能卡壳,那场面就会相当尴尬了。起初我还是对刷题比较抗拒的,感觉就跟学习交通法规一样,你花个半天时间就能背下来,就能考个九十多分,靠这个来面试实在是太low了。现在也释然了,一方面是现在人才太多了,企业已经没法通过面试来筛选人才,所以选择算法来做一层保底的筛选,如果你不会,就算你有多牛,也只能归类到垃圾的队伍了,所以这事得顺应时势,适者生存;另一方面比如字节这种公司确实对算法需求比较强,人家考核算法也是实际需要,也没必要觉得他是在有意刁难。

LeetCode题型

LeetCode应该怎么刷呢,首先很重要的一点是要多花时间,每天刷一两道题,保持好做题的感觉。这玩意熟能生巧,经常练习有助于治疗老年痴呆。另外我在网络收集了一些网友刷LeetCode的经验,对于初刷LeetCode的同学比较有用:

  • 按分类刷;每个分类从 Easy 到 Medium 顺序刷;
  • 优先刷 树、链表、二分查找、DFS、BFS 等面试常考类型;
  • 优先刷题号靠前的题目;
  • 优先刷点赞较多的题目;

本文主要是讲LeetCode中的数据结构以及考点,方便大家加深认识。这次我们首先讲的是LeetCode里的树。为什么先讲树呢,因为树是我们用的最多,实用性最强,也最容易在面试中被问到的一种数据结构,小到我们编程语言里的map,大到mysql的索引,都离不开树这个数据结构。可以这样说,你把树搞明白了,至少能应付一半的面试了。

在LeetCode的标签分类题库中,和树有关的标签有:树(227)、二叉树(198)、二叉搜索树(54)、字典树(49)、线段树(28)、树状数组(20)、最小生成树(5)。这些题中,二叉树又是树中的重点,可以归纳为:

上图主要是归纳了一些LeetCode常见题型和概念,方便大家记忆和查漏补缺。其中打星的是其中比较难的部分,不过这东西见仁见智,也许有些人也会觉得很简单。

下面帮大家回忆一下关于二叉树的基础概念。

要理解什么是二叉树,首先需要理解什么是树( tree )。可以使用递归的方式定义树:

一棵树是一些节点( node )的集合。这个集合可以是空集,说不是空集,则树由称作( root )的节点 r 以及0个或多个非空的(子)树T1, T2, ..., Tk组成,这些子树中每一棵都被来自根r的一条有向的( edge )所连接。

每一棵子树的根叫作根 r 的儿子 (child), 而 r 是每一棵子树的根的父亲 ( parent )。下图展示了用递归定义的典型的树:

在下面的树中,节点A是根。节点F有一个父亲A并且有儿子K、L和M。每一个节点可以有任意多个儿子,也可能是是零个儿子。没有儿子的节点称为树叶( leaf ),图中的树叶是B、C、H、I、P、Q、K、L、M和N。具有相同父亲的节点为兄弟 ( siblings )。因此,K、L和M都是兄弟。用类似的方法可以定义祖父( grandparent )和孙子( grandchild )关系。

从节点 n1 到 nk路径( path )定义为节点n1, n2, ..., nk的一个序列,是的对于 1 <= i < k 的节点ni是ni+1的父亲,这条路径的( length ) 是该路径上的边的条数,即 k-1。从每一个节点到他自己有一条长为0的路径。注意,在一棵树中从根到每个节点恰好存在一条路径。

对于任意节点ni,n深度( depth ) 为从根到 ni 的唯一路径的长。因此,根的深度为 0。节点 ni 的高( height )是从ni到一片树叶的最长路径的长。因此所有的树叶的高都是0。一棵树的高度( height of a tree )等于它的根的高。对于图中的树,E的深度为1而高为2;F的深度为1而高也是1;该树的高为3。一棵树的深度( depth of a tree )等于其最深的树叶的深度,该深度总是等于这棵树的高。

如果存在从n1到n2的一条路径,那么n1是n2的一位祖先( ancestor ),而n2是n1的一个后裔( descendant )。如果n1 != n2,那么n1是n2真祖先(proper ancestor),而n2是n1真后裔(proper descendant)。

二叉树

二叉树(Binary tree)是树形结构的一个重要类型,是AVL树,红黑树,二叉堆,大顶堆,小顶堆,多叉树的基础。那么什么是二叉树?下面给出二叉树的递归定义:

二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。

以上图为例,其中 6 是二叉树的根节点,A和B分别是根节点 6 的左子树和右子树;直线相连的节点分别是父节点和子节点,比如 6 是 2 和 8 的父节点,2 和 8 是 6 的子节点;没有子节点的节点叫叶子节点,比如 0、3、5、7、9 、10都是叶子节点。

相关术语

节点(node):包含一个数据元素及若干指向子树分支的信息。上图中的每个圆圈都表示一个节点。

度(degree):一个节点拥有子树的数目称为节点的度 ,叶子的度一定是0。上图中的6、2、8、4的度为2,9的度为1,0、3、5、7、9 、10的度为0。

叶子节点(leaf node:也称为外部节点(external node  outer node终端节点(terminal node,指没有子树的节点或者度为零的节点。上图中的0、3、5、7、9 、10都是叶子节点。

内部节点(internal node 或 inner node:也称为非终端节点分支节点branch node),度不为零的节点称为非终端节点。上图中的6、2、8、4、9都是内部节点。

树的度(degree of tree):树中所有节点的度的最大值。上面的树的度是2,二叉树的度不会超过2。

层(level:节点的层是沿着它和根节点之间的唯一路径的边数。LeetCode中的层是从0开始的,比如上图中的6是第0层,2是第一层。

距离(Distance):沿两个节点之间最短路径的边数。

有序树(Ordered tree):为每个顶点的子节点指定排序的有根树。

森林(Forest):由m(m≥0)棵互不相交的树构成一片森林。如果把一棵非空的树的根节点删除,则该树就变成了一片森林,森林中的树由原来根节点的各棵子树构成。

满二叉树(full binary tree):每个节点都有 0 或 2 个子节点的二叉树。

完全二叉树(complete binary tree):除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2个节点。下图所示是一棵完全二叉树:

完美二叉树(perfect binary tree):所有内部节点都有两个孩子并且所有叶子都具有相同深度或相同级别。一棵完美的树总是完全二叉树,但一棵完全二叉树不一定是完美的。

基本操作

递归

针对二叉树的问题的解决中,递归是一种十分常用的编程方式,有必要说明一下。

定义

数学和计算机科学中,递归指由一种(或多种)简单的基本情况定义的一类对象或方法,并规定其他所有情况都能被还原为其基本情况。

例如,下列为某人祖先的递归定义:

  • 某人的双亲是他的祖先(基本情况)。
  • 某人祖先的双亲同样是某人的祖先(递归步骤)。

斐波那契数列是典型的递归案例:

  • {\displaystyle F_{0}=0}(初始值)
  • {\displaystyle F_{1}=1}(初始值)
  • 对所有大于1的整数n:{\displaystyle F_{n}=F_{n-1}+F_{n-2}}(递归定义)

一种便于理解的心理模型,是认为递归定义对对象的定义是按照“先前定义的”同类对象来定义的。例如:你怎样才能移动100个箱子?答案:你首先移动一个箱子,并记下它移动到的位置,然后再去解决较小的问题:你怎样才能移动99个箱子?最终,你的问题将变为怎样移动一个箱子,而这时你已经知道该怎么做的。

C++的递归

直接或间接调用自己的函数称为递归函数(recursion function)。一个简单的定义函数的例子是阶乘的计算。数n的阶乘是从1到n的乘积。例如5的阶乘就是120。

1 * 2 * 3 * 4 * 5 = 120

解决这个问题的自然方法就是递归:

int factorial(int val)
{
if (val > 1)
return factorial(val-1)*val;
return 1;
}

递归函数必须定义一个终止条件;否则就会永远递归下去,这意味着函数会一直调用自身知道程序栈耗尽。有时候这种现象称为“无限递归错误”(infinite recursion error)。对于函数factorial,val为1是终止条件。

前序遍历

若二叉树非空,则依次执行如下操作:
⑴ 访问根结点;
⑵ 遍历左子树;
⑶ 遍历右子树。

中序遍历

若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵访问根结点;
⑶遍历右子树。

后序遍历

若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。

层序遍历

设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

引用:

https://blog.csdn.net/fuxuemingzhu/article/details/105183554

https://www.cnblogs.com/joelwang/p/10640599.html

https://www.cnblogs.com/liuzhen1995/p/11921771.html

https://leetcode-cn.com/circle/discuss/J8XFse/

https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91/1602879

https://www.jianshu.com/p/c5d48937f2d9

https://en.wikipedia.org/wiki/Binary_tree

https://en.wikipedia.org/wiki/Tree_(data_structure)

https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92

《C++ Primer 中文版》第4版

https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91%E9%81%8D%E5%8E%86/9796049?fr=aladdin

5分钟了解二叉树之LeetCode里的二叉树的更多相关文章

  1. LeetCode:翻转二叉树【226】

    LeetCode:翻转二叉树[226] 题目描述 翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 题目 ...

  2. 【Leetcode】104. 二叉树的最大深度

    题目 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,null,15,7 ...

  3. Leetcode 331.验证二叉树的前序序列化

    验证二叉树的前序序列化 序列化二叉树的一种方法是使用前序遍历.当我们遇到一个非空节点时,我们可以记录下这个节点的值.如果它是一个空节点,我们可以使用一个标记值记录,例如#. 例如,上面的二叉树可以被序 ...

  4. Java实现 LeetCode 331 验证二叉树的前序序列化

    331. 验证二叉树的前序序列化 序列化二叉树的一种方法是使用前序遍历.当我们遇到一个非空节点时,我们可以记录下这个节点的值.如果它是一个空节点,我们可以使用一个标记值记录,例如 #. _9_ / \ ...

  5. 【algo&ds】【吐血整理】4.树和二叉树、完全二叉树、满二叉树、二叉查找树、平衡二叉树、堆、哈夫曼树、B树、字典树、红黑树、跳表、散列表

    本博客内容耗时4天整理,如果需要转载,请注明出处,谢谢. 1.树 1.1树的定义 在计算机科学中,树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结 ...

  6. 遍历二叉树 traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化

    遍历二叉树   traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...

  7. javascript实现数据结构: 树和二叉树的应用--最优二叉树(赫夫曼树),回溯法与树的遍历--求集合幂集及八皇后问题

    赫夫曼树及其应用 赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用. 最优二叉树(Huffman树) 1 基本概念 ① 结点路径:从树中一个结点到另一个结点的之间的分支 ...

  8. [LeetCode] Path Sum 二叉树的路径和

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  9. 【LeetCode题解】二叉树的遍历

    我准备开始一个新系列[LeetCode题解],用来记录刷LeetCode题,顺便复习一下数据结构与算法. 1. 二叉树 二叉树(binary tree)是一种极为普遍的数据结构,树的每一个节点最多只有 ...

随机推荐

  1. Solution -「CF 623E」Transforming Sequence

    题目 题意简述   link.   有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...

  2. Note -「Mobius 反演」光速入门

    目录 Preface 数论函数 积性函数 Dirichlet 卷积 Dirichlet 卷积中的特殊函数 Mobius 函数 & Mobius 反演 Mobius 函数 Mobius 反演 基 ...

  3. suse 12 二进制部署 Kubernetets 1.19.7 - 第10章 - 部署kube-proxy组件

    文章目录 1.10.部署kube-proxy 1.10.0.创建kube-proxy证书 1.10.1.生成kube-proxy证书和秘钥 1.10.2.创建kube-proxy的kubeconfig ...

  4. tip8:CentOS8安装ftp服务器

    之前习惯使用OpenSuse,其图形化的安装.现在刚开始使用CentOS,老老实实使用命令吧! 1.本地cmd命令ftp链接虚拟机无法链接.查出虚拟机ftp服务是否开启:没有 ps -ef|grep ...

  5. 手撸一个springsecurity,了解一下security原理

    手撸一个springsecurity,了解一下security原理 转载自:www.javaman.cn 手撸一个springsecurity,了解一下security原理 今天手撸一个简易版本的sp ...

  6. CentOS7安装及配置 Zabbix全步骤,超详细教程

    服务器太多,还在不同的平台和账户,监控不便 整个 Zabbix 监控,开始吧 一.关闭防火墙并开机不启动 sudo setenforce 0 sudo sed -i "s/SELINUX=e ...

  7. C++ 序列操作函数最全总结

    标准库定义了许多用于操作序列的算法,大多在algorithm和numeric文件中,大多数函数的原理并不复杂,但是在很多情况下可以替代手写的情况,甚至更加优秀. 这类算法函数非常多,但是他们都有共同的 ...

  8. 攻防世界之Web_php_rce

    题目: ========================================================================== 解题思路: 1.这题主要考查ThinkPH ...

  9. Spring Cloud Gateway现高风险漏洞,建议采取措施加强防护

    大家好,我是DD 3月1日,Spring官方博客发布了一篇关于Spring Cloud Gateway的CVE报告. 其中包含一个高风险漏洞和一个中风险漏洞,建议有使用Spring Cloud Gat ...

  10. 思迈特软件与明略科技优势互补强强联合,快速迭代引领BI市场

    从全球范围看,自从上世纪80年代信息技术在企业应用中开始普及,至今一共经历了信息化.SaaS化.移动化和AI化四个阶段. 人工智能在中国发展的机遇和挑战 中国的AI创业公司之间竞争非常激烈,尤其表现在 ...