二叉树
文章平均质量分 56
二叉树
想名字多费事
编程小白入驻
展开
-
把二叉搜索树转换为累加树
看到累加可能会有一点麻烦,但二叉搜索树是有序树,那么有序的元素如何求累加呢?其实这就是⼀棵树,⼤家可能看起来有点别扭,换⼀个⻆度来看,这就是⼀个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。为什么变成数组就是感觉简单了呢?因为数组⼤家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了⼆叉搜索树,看起来就别扭了⼀些。那么知道如何遍历这个⼆叉树,也就迎刃⽽解了, 从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个⼆叉树,然后顺序.原创 2021-05-01 10:36:16 · 87 阅读 · 0 评论 -
将有序数组转为二叉搜索树
数组构造⼆叉树,构成平衡树是⾃然⽽然的事情。本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间。本题其实要⽐⼆叉树:构造⼆叉树登场! 和 ⼆叉树:构造⼀棵最⼤的⼆叉树简单⼀些,因为有序数组构造⼆叉搜索树,寻找分割点就⽐较容易了。分割点就是数组中间位置的节点。那么为问题来了,如果数组⻓度为偶数,中间节点有两个,取哪⼀个?取哪⼀个都可以,只不过构成了不同的平衡⼆叉搜索树。递归1、确定递归函数返回值及其参数除⼆叉树节点,增加⼆叉树节点,都是⽤递归函数的返回值来完成,这样是⽐较⽅便。那么本原创 2021-05-01 09:22:19 · 109 阅读 · 2 评论 -
修剪二叉搜索树
递归法1、确定递归函数的参数以及返回值我们需要返回值是因为是要遍历整棵树,做修剪操作,但其实不需要返回值也可以,我们也可以完成修剪(其实就是从⼆叉树中移除节点)的操作。只不过有返回值会更⽅便,可以通过递归函数的返回值来移除节点。 TreeNode* trimBST(TreeNode* root, int low, int high);2、确定终止条件修剪的操作并不是在终⽌条件上进⾏的,所以就是遇到空节点返回就可以了。if (root==NULL) return root;3、确定单层递.原创 2021-04-30 17:53:37 · 123 阅读 · 1 评论 -
删除二叉搜索树中的节点
递归法1、确定递归函数的参数和返回值说到递归函数的返回值,在⼆叉树:搜索树中的插⼊操作中通过递归返回值来加⼊新节点, 这⾥也可以通过递归返回值删除节点。TreeNode* deleteNode(TreeNode* root,int key);2、确定终止条件遇到空返回,说明没有找到删除的节点if(root==nullptr) return root;3、确定单层递归的逻辑删除节点会遇到5种情况:第⼀种情况:没找到删除的节点,遍历到空节点直接返回了找到删除的节点:第⼆种情况:左右孩.原创 2021-04-30 11:38:02 · 105 阅读 · 0 评论 -
二叉搜索树中的插入操作
递归1(带返回值)1、确定递归函数参数以及返回值TreeNode* insertIntoBST(TreeNode* root, int val)2、确定终止条件终⽌条件就是找到遍历的节点为null的时候,就是要插⼊节点的位置了,并把插⼊的节点返回。if (root == NULL) { TreeNode* node = new TreeNode(val); return node;}这⾥把添加的节点返回给上⼀层,就完成了⽗⼦节点的赋值操作了,详细再往下看。3、确定单层递归的.原创 2021-04-29 13:33:44 · 174 阅读 · 0 评论 -
二叉搜索树的最近公共祖先
递归法(未优化版)class Solution {public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root==p||root==q||root==NULL) return root; TreeNode* left=NULL; TreeNode* right=NULL; if(p->val<.原创 2021-04-28 17:32:20 · 69 阅读 · 0 评论 -
小结
1、迭代法中,⼀般⼀起操作两个树都是使⽤队列模拟类似层序遍历,同时处理两个树的节点,这种⽅式最好理解,如果⽤模拟递归的思路的话,要复杂⼀些。2、⼤多是⼆叉搜索树的题⽬,其实都离不开中序遍历,因为这样就是有序的。3、在⼀个有序序列求最值的时候,不要定义⼀个全局遍历,然后遍历序列更新全局变量求最值。因为最值可能就是int或者 longlong的最⼩值。推荐要通过前⼀个数值(pre)和后⼀个数值⽐较(cur),得出最值。4、在⼆叉树中通过两个前后指针作⽐较,会经常⽤到。5、需要明确:在有序数组求任意两数原创 2021-04-28 15:47:00 · 66 阅读 · 0 评论 -
二叉树的最近公共祖先
思路:1、利用回溯实现自底向上搜索,查找最近公共祖先。后序遍历就是一个回溯过程,最先处理的节点一定是叶子节点。2、怎样判断节点p和节点q的最近公共祖先呢?(1)、某个节点是节点p和节点q的公共祖先:如果找到一个节点,发现左子树出现节点p,右子树出现节点q。或者左子树出现节点q,右子树出现节点p,则该节点就是节点p和节点q的最近公共祖先。(2)节点p或节点q是节点p和节点q的公共祖先:某一个节点左/右子树出现p/q,右/左子树为空递归法1、确定递归函数的参数和返回值:需要递归函数的返回值来告.原创 2021-04-27 17:56:01 · 4918 阅读 · 2 评论 -
二叉搜索树中的众数
假设这棵树不是二叉搜索树,是一棵普通的树,则递归法如下:/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(n.原创 2021-04-26 11:44:10 · 115 阅读 · 0 评论 -
二叉搜索树的最小绝对差
注意是⼆叉搜索树,⼆叉搜索树可是有序的。遇到在⼆叉搜索树上求什么最值啊,差值之类的,就把它想成在⼀个有序数组上求最值,求差值,这样就简单多了。递归法1最直观的想法,就是把⼆叉搜索树转换成有序数组,然后遍历⼀遍数组,就统计出来最⼩差值了。class Solution {public: void traversal(TreeNode* root,vector<int>& vec){ if(root==nullptr) return; tra.原创 2021-04-25 16:59:11 · 59 阅读 · 0 评论 -
验证二叉搜索树
中序遍历下,输出的⼆叉搜索树节点的数值是有序序列,有了这个特性, 验证⼆叉搜索树,就相当于变成了判断⼀个序列是不是递增的了。递归法1(将二叉搜索树转变为一个数组)class Solution{public: void traversal(TreeNode* root,vector<int>& vec){ if(root==NULL) return; traversal(root->left,vec); vec.push_ba.原创 2021-04-25 13:35:37 · 68 阅读 · 0 评论 -
二叉搜索树中的搜索
思路⼆叉搜索树是⼀个有序树:若它的左⼦树不空,则左⼦树上所有结点的值均⼩于它的根结点的值;若它的右⼦树不空,则右⼦树上所有结点的值均⼤于它的根结点的值;它的左、右⼦树也分别为⼆叉搜索树递归法class Solution {public: TreeNode* searchBST(TreeNode* root, int val) { if(root==nullptr||val==root->val) return root;//递归终止条件,如果root为空,或者找.原创 2021-04-24 16:22:37 · 81 阅读 · 0 评论 -
合并两个二叉树
递归法class Solution {public: TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) { if(root1==nullptr) return root2; if(root2==nullptr) return root1; TreeNode* root=new TreeNode(0); root->val=root1->val+r.原创 2021-04-24 14:54:22 · 163 阅读 · 0 评论 -
构造最大的二叉树
递归法(容器分割)前序遍历先构造中间结点,然后递归构造左子树和右子树1、确定递归函数的参数和返回值参数就是传⼊的是存放元素的数组,返回该数组构造的⼆叉树的头结点,返回类型是指向节点的指针。TreeNode* constructMaximumBinaryTree(vector<int>& nums)2、确定终⽌条件题⽬中说了输⼊的数组⼤⼩⼀定是⼤于等于1的,所以我们不⽤考虑⼩于1的情况,那么当递归遍历的时候,如果传⼊的数组⼤⼩为1,说明遍历到了叶⼦节点了。那么应该定义⼀个.原创 2021-04-24 10:26:07 · 220 阅读 · 0 评论 -
如何根据两个顺序构造⼀个唯⼀的⼆叉树?
本题思路根据Carl大佬整理,大家感兴趣的去关注一波。如果你想提升算法能力,只要跟住代码随想录每天题目的节奏,定会融会贯通,算法能力稳稳的提升一个台阶!⾸先如何根据两个顺序构造⼀个唯⼀的⼆叉树,就是以 后序数组的最后⼀个元素为切割点,先切中序数组,根据中序数组,反过来在切后序数组。⼀层⼀层切下去,每次后序数组最后⼀个元素就是节点元素。...原创 2021-04-22 19:12:00 · 225 阅读 · 0 评论 -
路径总和
思路:遍历从根节点到叶子节点的路径看看有没有路径总和是目标和。递归法可使用深度优先遍历的方式(前中后序遍历)来遍历二叉树。1、确定递归函数的参数和返回类型参数:需要二叉树的根节点,还需要一个int型计数器用来计算二叉树的一条路径是否正好是目标和。bool traversal(TreeNode* root,int count)2、确定终止条件让计数器count初始为⽬标和,然后每次减去遍历路径节点上的数值。如果最后count==0,同时到了叶子节点的话,说明找到了目标和。如果遍历到了叶子节.原创 2021-04-20 15:51:15 · 85 阅读 · 0 评论 -
树左下角的值
递归法题目要求在树的最后一行找到最左边的值用递归法如何判断是最后一行?其实就是深度最大的叶子节点一定是最后一行。如何找最左边的深度最大的叶子节点呢?可以使用前序遍历优先在左边进行搜索。然后记录深度最大的叶子节点,此时就是最后一行最左边的值。1、确定递归函数的参数及返回值参数必须有要遍历树的根节点,要有int型的变量用来记录深度最大的叶子节点。此时就是树的最后一行最左边的值int maxDepth=INT_MIN;//全局变量,用来记录最大深度int maxleftValue;//全局变量 .原创 2021-04-20 10:44:00 · 93 阅读 · 0 评论 -
左叶子之和
注:左叶子其实就是左节点不为空,且左节点没有左右孩子,那么这个节点就是左叶子。判断当前结点是否是左叶子必须要通过它的父节点来判断其左孩子是不是左叶子。if(node->left!=nullptr&&node->left->left==nullptr&&node->left->right==nullptr) { 左叶子节点处理逻辑}递归法递归遍历顺序是后序遍历(左右中),因为要通过递归函数的返回值来累加求取左叶子数值之和。1、.原创 2021-04-19 20:35:02 · 120 阅读 · 0 评论 -
二叉树的所有路径
思路题目要我们求从根节点到叶子节点的路径,所以需要前序遍历,这样会很方便的让父节点指向孩子节点,从而找到对应的路径。本题中会用到回溯,因为要把路径记录下来,然后回溯一个路径到另一个路径。递归法1、确定递归函数的参数和返回值要传入根节点,记录每一条路径的path,存放结果集的result,返回值无void traversal(TreeNode* cur,vector<int>& path,vector<string>& result)2、确定递归的终.原创 2021-04-18 16:49:09 · 177 阅读 · 0 评论 -
平衡二叉树
因为求深度可以从上到下去查所以需要前序遍历(中左右),⽽⾼度只能从下到上去查,所以只能后序遍历(左右中)有的同学⼀定疑惑,为什么求⼆叉树的最⼤深度时也⽤的是后序遍历。那是因为代码的逻辑其实是求的根节点的⾼度,⽽根节点的⾼度就是这棵树的最⼤深度,所以才可以使⽤后序遍历。如果真正求取⼆叉树的最⼤深度,代码应该写成如下:(前序遍历)class Solution{public: int result; void getDepth(TreeNode* node,int depth) { ..原创 2021-04-18 12:56:58 · 163 阅读 · 0 评论 -
完全二叉树的结点个数
递归法1、确定递归函数的参数和返回值:参数就是传⼊树的根节点,返回就返回以该节点为根节点⼆叉树的节点数量,所以返回值为int类型。int countNodes(TreeNoed* root)2、确定终⽌条件:如果为空节点的话,就返回0,表示节点数为0。代码如下:if(node==nullptr) return 0;3、确定单层递归的逻辑:先求它的左⼦树的节点数量,再求的右⼦树的节点数量,最后取总和再加⼀(加1是因为算上当前中间节点)就是⽬前节点为根节点的节点数量。 int leftnode.原创 2021-04-18 09:51:13 · 3485 阅读 · 0 评论 -
二叉树的最小深度
题⽬中说的是:最⼩深度是从根节点到最近叶⼦节点的最短路径上的节点数量。注意是叶⼦节点。什么是叶⼦节点,左右孩⼦都为空的节点才是叶⼦节点!递归法1、确定递归的参数和返回值:参数为要传入的二叉树的根节点,返回的是int 型的深度。int getDepth(TreeNode* node)2、确定终止条件if(node==nullptr) return 0;3、确定单层递归的逻辑错误代码 int leftdepth=getDepth(node->left); int righ.原创 2021-04-17 17:07:10 · 124 阅读 · 0 评论 -
二叉树的最大深度
递归法1、确定递归函数的参数和返回值:参数就是传⼊树的根节点,返回值就是返回这棵树的深度,所以返回值为int类型。int getDepth(TreeNode* node);2、确定终止条件:当节点为空的时候,就返回0,表示高度为0if(node==nullptr) return 0;3、确定单层递归的逻辑:先求它的左⼦树的深度,再求的右⼦树的深度,最后取左右深度最⼤的数值再+1(加1是因为算上当前中间节点)就是⽬前节点为根节点的树的深度。int leftDepth=getDepth(nod.原创 2021-04-17 14:25:39 · 85 阅读 · 0 评论 -
对称二叉树
思路:要判断二叉树是不是对称的,要想好比较的是哪两个结点,观察可知,判断二叉树是否对称,要比较的是根结点的左右子树是不是相互翻转的,所以递归遍历过程中,要同时遍历两棵树。做法:比较两棵子树的里侧和外侧的元素是否相等。本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个⼦树的内侧节点和外侧节点是否相等。正是因为要遍历两棵树⽽且要⽐较内侧和外侧节点,所以准确的来说是⼀个树的遍历顺序是左右中,⼀个树的遍历顺序是右左中。但都可以理解算是后序遍历,尽管已经不是严格上在⼀个树上进⾏遍历的后序遍.原创 2021-04-17 11:10:47 · 118 阅读 · 0 评论 -
N叉树的前序遍历
/*// Definition for a Node.class Node {public: int val; vector<Node*> children; Node() {} Node(int _val) { val = _val; } Node(int _val, vector<Node*> _children) { val = _val; children = _ch.原创 2021-04-16 19:19:16 · 62 阅读 · 0 评论 -
翻转二叉树
文章目录前言一、翻转二叉树二、打法1.递归法2.读入数据总结前言热闹不过是短暂的消耗品,而撑起你人生的是孤独本身一、翻转二叉树观察可以发现,如要翻转整个二叉树,就在遍历的过程中去翻转每⼀个节点的左右孩⼦就可以达到整体翻转的效果。二、打法1.递归法1、确定递归函数的参数和返回值参数就是要传⼊节点的指针,返回值题⽬中给出要返回root节点的指针,所以函数的返回类型为TreeNode*。2、确定终⽌条件当前节点为空的时候,就返回3、确定单层递归的逻辑因为是先做前序遍历,所以先进⾏交换左原创 2021-04-16 18:37:57 · 285 阅读 · 0 评论 -
二叉树的层序遍历
文章目录前言一、层序遍历是什么?二、实现方法(leetcode 102题为例)打怪升级1打怪升级2打怪升级3打怪升级4打怪升级6打怪升级7打怪升级8总结前言要成为绝世高手,并非一朝一夕,除非是天生武学奇才,但这种人…万中无一-------包租婆一、层序遍历是什么?二叉树的层序遍历,就是从左到右一层一层的去遍历二叉树。需要借助队列这种数据结构来实现,队列先进先出,符合一层一层遍历的逻辑。而用栈先进后出模拟深度优先遍历也就是递归的逻辑。二、实现方法(leetcode 102题为例)calss原创 2021-04-15 17:56:57 · 2238 阅读 · 1 评论 -
二叉树的前中后序遍历之迭代法(统一风格迭代方式)
一、前序遍历(迭代法)->右左中前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。为什么要先加入 右孩子,再加入左孩子呢?因为这样出栈的时候才是中左右的顺序。注:前序遍历要访问的元素和要处理的元素顺序是一致的,都是中间节点class Solution {public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res原创 2021-04-05 21:02:48 · 434 阅读 · 0 评论 -
二叉树的前中后序遍历之迭代法(非统一风格迭代方式)
文章目录前言一、前序遍历(迭代法)1.代码实现二.中序遍历(迭代法)三、后序遍历(迭代法)总结前言「递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中」,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。所以我们用栈也可以是实现二叉树的前后中序遍历。一、前序遍历(迭代法)前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。为什么要先加入 右孩子,再加入左孩子呢?因.原创 2021-04-05 16:41:05 · 424 阅读 · 0 评论 -
二叉树的前中后序遍历的递归写法
文章目录一、递归算法的三段论?二、运用步骤【以前序遍历为例】总结一、递归算法的三段论?1、确定递归函数的参数和返回值【确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。】2、确定终止条件【写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。】3、确定单层递归的逻辑【确.原创 2021-04-05 13:41:25 · 600 阅读 · 0 评论 -
二叉树的基础知识
文章目录前言一、你应该具备的基础知识二、二叉树的种类有哪些?1、满二叉树2、完全二叉树3、二叉搜索树(二叉排序树)4、平衡二叉搜索树小结三、二叉树的存储方式1、链式存储(最重要)2、顺序存储(了解)四、二叉树的遍历方式小结五、二叉树的定义(要能手撕)六、总结前言提示:二叉树是一种重要的数据结构,也是面试和笔试的重头,接下来我们要系统性的总结二叉树的知识点。一、你应该具备的基础知识1、结点的度:树中结点拥有的子树个数。度为0的结点原创 2021-04-05 11:36:45 · 606 阅读 · 1 评论