【树】
文章平均质量分 79
LeetCode上 数据结构 为树类题目
Ring*
本科学硬件,研究生学软件!
展开
-
【LeetCode-589】 N 叉树的前序遍历
在前序遍历中,我们会先遍历节点本身,然后从左向右依次先序遍历该每个以子节点为根的子树,此时利用栈先进后出的原理,依次从右向左将子节点入栈,这样出栈的时候即可保证从左向右依次遍历每个子树。随后每次我们从栈顶取出一个节点 u,它是我们当前遍历到的节点,并把 u 的所有子节点从右向左逆序压入栈中,这样出栈的节点则是顺序从左向右的。递归思路比较简单,N 叉树的前序遍历与二叉树的前序遍历的思路和方法基本一致,可以参考「144. 二叉树的前序遍历」的方法,每次递归时,先访问根节点,然后依次递归访问每个孩子节点即可。原创 2022-09-08 09:14:58 · 253 阅读 · 1 评论 -
【LeetCode-116】填充每个节点的下一个右侧节点指针
层次遍历基于广度优先搜索,它与广度优先搜索的不同之处在于,广度优先搜索每次只会取出一个节点来拓展,而层次遍历会每次将队列中的所有元素都拿出来拓展,这样能保证每次从队列中拿出来遍历的元素都是属于同一层的,因此我们可以在遍历的过程中修改每个节点的 next 指针,同时拓展下一层的新队列。由于已经在父节点这一层建立了 next 指针,因此可以直接通过第一个父节点的 next 指针找到第二个父节点,然后在它们的孩子之间建立连接。第 N 层节点之间建立 next 指针后,再建立第 N+1 层节点的 next 指针。原创 2022-09-08 09:13:43 · 210 阅读 · 0 评论 -
【LeetCode-230】二叉搜索树中第K小的元素
我们注意到在方法二中搜索二叉搜索树的时间复杂度为 O(H),其中 H 是树的高度;因此,我们在记录子树的结点数的基础上,将二叉搜索树转换为平衡二叉搜索树,并在插入和删除操作中维护它的平衡状态。其中,将二叉搜索树转换为平衡二叉搜索树,可以参考「1382. 将二叉搜索树变平衡的官方题解」。「二叉树的中序遍历」可以参考「94. 二叉树的中序遍历的官方题解」,具体地,我们使用迭代方法,这样可以在找到答案后停止,不需要遍历整棵树。因为二叉搜索树和中序遍历的性质,所以二叉搜索树的中序遍历是按照键增加的顺序进行的。原创 2022-09-08 09:10:42 · 736 阅读 · 0 评论 -
【LeetCode-107】二叉树的层序遍历II
为了降低在结果列表的头部添加一层节点值的列表的时间复杂度,结果列表可以使用链表的结构,在链表头部添加一层节点值的列表的时间复杂度是 O(1)。如果要求从上到下输出每一层的节点值,做法是很直观的,在遍历完一层节点之后,将存储该层节点值的列表添加到结果列表的尾部。这道题要求从下到上输出每一层的节点值,只要对上述操作稍作修改即可:在遍历完一层节点之后,将存储该层节点值的列表添加到结果列表的头部。树的层次遍历可以使用广度优先搜索实现。从根节点开始搜索,每次遍历同一层的全部节点,使用一个列表存储该层的节点值。原创 2022-09-08 09:06:15 · 124 阅读 · 0 评论 -
【LeetCode-222】 完全二叉树的节点个数
根据完全二叉树的特性可知,完全二叉树的最左边的节点一定位于最底层,因此从根节点出发,每次访问左子节点,直到遇到叶子节点,该叶子节点即为完全二叉树的最左边的节点,经过的路径长度即为最大层数 h。具体做法是,根据节点个数范围的上下界得到当前需要判断的节点个数 k,如果第 k 个节点存在,则节点个数一定大于或等于 k,如果第 k 个节点不存在,则节点个数一定小于 k,由此可以将查找的范围缩小一半,直到得到节点个数。当最底层包含 1 个节点时,完全二叉树的节点个数是。个节点,最底层包含的节点数最少为 1,最多为。原创 2022-09-08 09:04:50 · 133 阅读 · 0 评论 -
【LeetCode-236】二叉树的最近公共祖先
说明左子树和右子树均包含 p 节点或 q 节点,如果左子树包含的是 p 节点,那么右子树只能包含 q 节点,反之亦然,因为 p 节点和 q 节点都是不同且唯一的节点,因此如果满足这个判断条件即可说明 x 就是我们要找的最近公共祖先。我们可以用哈希表存储所有节点的父节点,然后我们就可以利用节点的父节点信息从 p 结点开始不断往上跳,并记录已经访问过的节点,再从 q 节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。本身的定义很巧妙,在找到最近公共祖先 x 以后,原创 2022-09-08 09:02:51 · 105 阅读 · 0 评论 -
【LeetCode-113】路径总和 II
注意到本题的要求是,找到所有满足从「根节点」到某个「叶子节点」经过的路径上的节点之和等于目标和的路径。核心思想是对树进行一次遍历,在遍历时记录从根节点到当前节点的路径和,以防止重复计算。原创 2022-09-08 09:00:37 · 196 阅读 · 0 评论 -
【LeetCode-129】求根节点到叶节点数字之和
这道题中,二叉树的每条从根节点到叶子节点的路径都代表一个数字。其实,每个节点都对应一个数字,等于其父节点对应的数字乘以 10 再加上该节点的值(这里假设根节点的父节点对应的数字是 0)。只要计算出每个叶子节点对应的数字,然后计算所有叶子节点对应的数字之和,即可得到结果。可以通过深度优先搜索和广度优先搜索实现。原创 2022-09-08 08:58:41 · 736 阅读 · 0 评论 -
【LeetCode-98】
那么根据二叉搜索树的性质,在递归调用左子树时,我们需要把上界 upper 改为 root.val,即调用 helper(root.left, lower, root.val),因为左子树里所有节点的值均小于它的根节点的值。基于方法一中提及的性质,我们可以进一步知道二叉搜索树「中序遍历」得到的值构成的序列一定是升序的,这启示我们在中序遍历的时候实时检查当前节点的值是否大于前一个中序遍历到的节点的值即可。如果均大于说明这个序列是升序的,整棵树是二叉搜索树,否则不是,下面的代码我们使用栈来模拟中序遍历的过程。原创 2022-09-08 08:57:02 · 134 阅读 · 0 评论 -
【LeetCode-257】二叉树的所有路径
我们维护一个队列,存储节点以及根到该节点的路径。在每一步迭代中,我们取出队列中的首节点,如果它是叶子节点,则将它对应的路径加入到答案中。如果它不是叶子节点,则将它的所有孩子节点加入到队列的末尾。当队列为空时广度优先搜索结束,我们即能得到答案。如此,当遍历完整棵二叉树以后我们就得到了所有从根节点到叶子节点的路径。当然,深度优先搜索也可以使用非递归的方式实现,这里不再赘述。在深度优先搜索遍历二叉树时,我们需要考虑当前的节点以及它的孩子节点。,返回所有从根节点到叶子节点的路径。是指没有子节点的节点。原创 2022-09-08 08:55:25 · 72 阅读 · 0 评论 -
【LeetCode-111】二叉树的最小深度
对于每一个非叶子节点,我们只需要分别计算其左右子树的最小叶子节点深度。这样就将一个大问题转化为了小问题,可以递归地解决该问题。当我们找到一个叶子节点时,直接返回这个叶子节点的深度。广度优先搜索的性质保证了最先搜索到的叶子节点的深度一定最小。首先可以想到使用深度优先搜索的方法,遍历整棵树,记录最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。同样,我们可以想到使用广度优先搜索的方法,遍历整棵树。**说明:**叶子节点是指没有子节点的节点。给定一个二叉树,找出其最小深度。原创 2022-09-07 14:44:56 · 53 阅读 · 0 评论 -
【LeetCode-235】二叉搜索树的最近公共祖先
因此,如果我们设从根节点到 p 的路径为数组 path_p,从根节点到 q 的路径为数组 path_q,那么只要找出最大的编号 i,其满足 path_p[i]=path_q[i]百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。我们也可以考虑将这两个节点放在一起遍历。在寻找节点的过程中,我们可以顺便记录经过的节点,这样就得到了从根节点到被寻找节点的路径。原创 2022-09-07 14:43:41 · 132 阅读 · 0 评论 -
【LeetCode-102】二叉树的层序遍历
我们可以想到最朴素的方法是用一个二元组 (node, level) 来表示状态,它表示某个节点和它所在的层数,每个新进队列的节点的 level 值都是父亲节点的 level 值加一。最后根据每个点的 level 对点进行分类,分类的时候我们可以利用哈希表,维护一个以 level 为键,对应节点值组成的数组为值,广度优先搜索结束以后按键 level 从小到大取出所有值,组成答案返回即可。它和普通广度优先搜索的区别在于,普通广度优先搜索每次只取一个元素拓展,而这里每次取。记树上所有节点的个数为 n。原创 2022-09-07 14:42:10 · 154 阅读 · 0 评论 -
【LeetCode-226】翻转二叉树
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。,翻转这棵二叉树,并返回其根节点。给你一棵二叉树的根节点。原创 2022-09-07 14:40:41 · 59 阅读 · 0 评论 -
【LeetCode-101】对称二叉树
每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。我们可以实现这样一个递归函数,通过「同步移动」两个指针的方法来遍历这棵树,p 指针和 q 指针一开始都指向这棵树的根,随后 p 右移时,q 左移,p 左移时,q 右移。如果一个树的左子树与右子树镜像对称,那么这个树是对称的。因此,该问题可以转化为:两个树在什么情况下互为镜像?原创 2022-09-07 14:39:11 · 44 阅读 · 0 评论 -
【LeetCode-404】左叶子之和
一个节点为「左叶子」节点,当且仅当它是某个节点的左子节点,并且它是一个叶子结点。因此我们可以考虑对整棵树进行遍历,当我们遍历到节点 node 时,如果它的左子节点是一个叶子结点,那么就将它的左子节点的值累加计入答案。遍历整棵树的方法有深度优先搜索和广度优先搜索,下面分别给出了实现代码。,返回所有左叶子之和。原创 2022-09-07 14:30:39 · 150 阅读 · 0 评论 -
【LeetCode-112】路径总和
不难发现这满足递归的性质,若当前节点就是叶子节点,那么我们直接判断 sum 是否等于 val 即可(因为路径和已经确定,就是当前节点的值,我们只需要判断该路径和是否满足条件)。假定从根节点到当前节点的值之和为 val,我们可以将这个大问题转化为一个小问题:是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val。观察要求我们完成的函数,我们可以归纳出它的功能:询问是否存在从当前节点 root 到叶子节点的路径,满足其路径和为 sum。叶子节点 是指没有子节点的节点。原创 2022-09-07 14:24:46 · 67 阅读 · 0 评论 -
【LeetCode-104】二叉树的最大深度
每次拓展下一层的时候,不同于广度优先搜索的每次只从队列里拿出一个节点,我们需要将队列里的所有节点都拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是当前层的所有节点,即我们是一层一层地进行拓展,最后我们用一个变量 ans 来维护拓展的次数,该二叉树的最大深度即为 ans。具体而言,在计算当前二叉树的最大深度时,可以先递归计算出其左子树和右子树的最大深度,然后在 O(1) 时间内计算出当前二叉树的最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点。原创 2022-09-07 11:02:31 · 141 阅读 · 0 评论 -
【LeetCode-100】相同的树
如果两个二叉树都不为空,那么首先判断它们的根节点的值是否相同,若不相同则两个二叉树一定不同,若相同,再分别判断两个二叉树的左子树是否相同以及右子树是否相同。同样首先判断两个二叉树是否为空,如果两个二叉树都不为空,则从两个二叉树的根节点开始广度优先搜索。如果只有一个队列为空,则两个二叉树的结构不同,因此两个二叉树不同。如果两个二叉树都为空,则两个二叉树相同。如果两个二叉树中有且只有一个为空,则两个二叉树一定不相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。给你两棵二叉树的根节点。原创 2022-09-07 11:00:48 · 73 阅读 · 0 评论 -
【LeetCode-94】二叉树的中序遍历
定义 inorder(root) 表示当前遍历到 root 节点的答案,那么按照定义,我们只要递归调用 inorder(root.left) 来遍历 root 节点的左子树,然后将 root 节点的值加入答案,再递归调用 inorder(root.right) 来遍历 root 节点的右子树即可,递归终止的条件为碰到空节点。方法一的递归函数我们也可以用迭代的方式实现,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其他都相同,具体实现可以看下面的代码。原创 2022-09-07 10:58:10 · 102 阅读 · 0 评论