树
tree
baixiaofei567
如果十年前没种树,那最好的时间是现在
展开
-
938. 二叉搜索树的范围和
利用bst的特性做,如果当前结点符合,就让sum加上当前的,并递归左右。如果当前小于low,就去右边就行了,否则就去左边。最后返回sum。一开始考虑中序遍历,很明显这样很快,O(logn),中序就是O(n)了class Solution {public: void dfs(TreeNode* root, int low ,int high){ if(root == nullptr) return; //根据low和high和val递归左边or右边 ..原创 2021-04-28 00:24:28 · 115 阅读 · 0 评论 -
897. 递增顺序搜索树
不用保存,直接修改cur的right就行了,但是要注意一点!!将root的left设为空,这个不会影响后序,因为root的left一定已经被访问过了/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(null..原创 2021-04-25 23:58:00 · 130 阅读 · 0 评论 -
783. 二叉搜索树节点最小距离
两种方法,递归和迭代,总的来说就是不难,bst任意两个点的最小差,还不就是中序遍历两两相减吗?为了防止数据太恶心,我们维护的是pre结点,不是int的pre,递归就是第一次不比较,但是要更新pre为root。不管有没有更新res,pre都要在比较后更新。迭代也是一样第一次不比较class Solution {public: // void inOrderTrave(TreeNode* root){ // if(root == nullptr) return; // .原创 2021-04-14 00:31:03 · 116 阅读 · 0 评论 -
501. 二叉搜索树中的众数
和之前pat的dfs很像,维护一个num记录之前的结点出现的次数,再维护一个pre。class Solution {public: //pre不能通过传参更新,如果是回溯的,那就获取不到上一层的结点了,因为它不是经过调用得来的,而是自动回溯的 void inorderTrave(TreeNode* root){ if(root == nullptr) return; inorderTrave(root->left); if(root.原创 2021-03-24 02:03:37 · 109 阅读 · 0 评论 -
530. 二叉搜索树的最小绝对差
一开始维护一个vector,两两相减求最小值。还有一个O(1)空复的,就是维护一个pre就行了,pre同时是一个flag,如果不是-1的情况,就用pre和root->val来更新一下minnclass Solution {public: void inorderTrave(TreeNode* root){ if(root == NULL) return; inorderTrave(root->left); //pre是个flag .原创 2021-03-24 01:59:34 · 104 阅读 · 0 评论 -
653. 两数之和 IV - 输入 BST
最优解肯定是中序+双指针夹逼class Solution {public: void dfs(TreeNode* root){ if(root == nullptr) return; //用中序 dfs(root->left); res.push_back(root->val); dfs(root->right); } bool findTarget(TreeNode* root..原创 2021-03-24 01:55:45 · 125 阅读 · 0 评论 -
109. 有序链表转换二叉搜索树
和有序数组建BST基本一样多了几道复杂的工序罢了,左右边界通过链表走到空来确定,不是用l和r了。用快慢指针来确定mid结点。然后再次遍历,将slow的前一个结点指向nullptr,这个很重要。当head为空就是递归边界返回null即可class Solution {public: TreeNode* sortedListToBST(ListNode* head) { //通过快慢指针将链表切分,递归构造左右子树 //递归边界是l>r的情况,也就是hea.原创 2021-03-24 01:52:16 · 99 阅读 · 0 评论 -
235. 二叉搜索树的最近公共祖先
bst的lca其实比普通二叉树的lca巧妙一点。因为不确定p和q哪个比较大,所以如果当前root 的值大于p和q就去左边找,小于就去右边。其余情况直接返回root,比如介于p和q之间或者介于q和p之间class Solution {public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { //并不保证p<q //如果当前结点的值大于p和q,就去右..原创 2021-03-23 01:33:45 · 128 阅读 · 0 评论 -
669. 修剪二叉搜索树
不简单的递归如果当前结点不符合要求,有两种情况1.小于low,所以root和左子树都不要了,要的是修改后的右子树,递归修改右子树然后返回。2.大于high如果正常,就递归修改自己的左边和右边,然后返回rootclass Solution {public: TreeNode* trimBST(TreeNode* root, int low, int high) { if(root == nullptr) return root; //判断当前结点是否符合..原创 2021-03-23 01:29:35 · 85 阅读 · 0 评论 -
513. 找树左下角的值
简单的bfsclass Solution {public: int findBottomLeftValue(TreeNode* root) { //记录深度的层序遍历,用一个vector记录每一层就行了,或者用一个bool值来更新 queue<TreeNode*> q; vector<int> vec; int res = 0; q.push(root); while(!q..原创 2021-03-22 01:28:57 · 62 阅读 · 0 评论 -
637. 二叉树的层平均值
将levelSum强转成double再进行除法,不要先进行除法再强转成double,不然会精度丢失class Solution {public: vector<double> averageOfLevels(TreeNode* root) { vector<double> vec; if(root == nullptr) return vec; int levelSize = 0; long levelSu.原创 2021-03-22 01:27:43 · 115 阅读 · 0 评论 -
671. 二叉树中第二小的节点
不难的题,其实就是找第一个和根结点不同的值,所以我们写个dfs把根结点的值传进去作比较就行了,如果当前结点不等于root,就更新res,然后直接return!!很重要,这是剪枝操作。如果最后res没有更新过就返回-1class Solution {public: void dfs(TreeNode* root, int val){ if(root == nullptr) return; if(root->val != val){ /...原创 2021-03-22 01:20:40 · 89 阅读 · 0 评论 -
687. 最长同值路径
还是典型的双重dfs,先用第一层dfs搜索到每个点,然后对每个点进行dfs,第二层dfs的内容是判断和根的值是否相同,如果相同就加上当前结点的深度,并且计算当前左右子树能提供的最大深度+1。如果不相等,直接返回0。第一层dfs中对每个结点再次进行dfs的内容的时传进自身的值的左右结点,用左+右来更新res。class Solution {public: int dfs2(TreeNode* root,int val){ if(root == nullptr) return ..原创 2021-03-22 01:09:33 · 88 阅读 · 0 评论 -
404. 左叶子之和
来一个res记录,如果为空就返回0,不然就判断当前结点的左子结点是否为空,如果不为空就判断当前结点的左子结点是否为叶子,如果是叶子,就更新res,然后递归左右,最后返回res。最重要的是不用管自身是什么结点,只需要判断自己的左子结点就行了,还一直在纠结怎么判断自己是什么结点的就错了class Solution {public: int sumOfLeftLeaves(TreeNode* root) { if(root == NULL) return 0; if.原创 2021-03-21 02:52:18 · 145 阅读 · 0 评论 -
111. 二叉树的最小深度
不是简单的求深度,是对每一条路径求深度,来一个res记录最小的,tmp记录当前深度,当到叶子结点就更新res。不为空就让当前深度+1,如果不是叶子结点,就递归左右。class Solution {public: void dfs(TreeNode* root, int tmp){ if(root == nullptr) return; tmp += 1; if(root->left == nullptr && root-..原创 2021-03-21 02:49:58 · 108 阅读 · 0 评论 -
572. 另一个树的子树
和另一道题很像,但是又不太一样,也是一道双重dfs的题。找到s中和t相等的结点后对其进行第二次dfsclass Solution {public: bool dfs2(TreeNode* s,TreeNode* t){ //现在是要完全相同的结构,所以遍历到空就停止了 //但是如果不用完全相等,比如t已经结束了,s下面还有,那也是相等的,就比较复杂 if(s == nullptr && t == nullptr) return ..原创 2021-03-21 02:47:30 · 67 阅读 · 0 评论 -
112. 路径总和
用自身函数做递归就行了,重点重点,root为空返回false,怎么解释我也不知道。让target减去当前结点,如果当前结点为叶子结点,就判断target是否为0,为0就返回true,证明有一种可行的情况,否则返回false。如果不是叶子结点,递归搜索左子树和右子树,用||来连接,有一个可行的就行了class Solution {public: bool hasPathSum(TreeNode* root, int targetSum) { //我们要的是到叶子结点的情况,..原创 2021-03-21 02:42:35 · 81 阅读 · 0 评论 -
树的三序遍历(迭代)
先序class Solution {public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; if(root == nullptr) res; stack<TreeNode*> sta; sta.push(root); while(!sta.empty()){ root原创 2021-03-09 23:07:14 · 256 阅读 · 1 评论 -
113. 路径总和 II
简单的回溯/** * 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(nullptr), right(nullpt...原创 2021-03-07 01:42:00 · 60 阅读 · 0 评论 -
95. 不同的二叉搜索树 II
这道分治也是好题!分治建左右两边的树,用两个treenode数组去接递归建两边树的结果,然后遍历两个数组,一定一定一定要在循环内部建立root,非常重要,不然你在外面建立root,不管你怎么改left和right,都是同一个root,甚至会修改在数组中的结果,/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right.原创 2021-02-22 01:14:17 · 161 阅读 · 0 评论 -
230. 二叉搜索树中第K小的元素
bst的中序遍历就是从小到大的法一:递归,来一个index时刻记录当前数字是第几个被遍历到的,如果index==k,就将全局的res赋值。法二:迭代,迭代中序必须记住,不论root的right是否为空,都要将root变为root->right/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; ..原创 2021-02-14 01:38:32 · 105 阅读 · 0 评论 -
116. 填充每个节点的下一个右侧节点指针
满二叉树就很简单,在当前层操控下一层,递归就行了,如果当前结点为空,或者下一层为空直接返回,因为当前层一定被上一层修改好了,如果没有下一层要修改了当然直接返回就行了。将root的左子结点的next指向右子结点,如果root的next不为空,就将右子结点的next指向root的next的左子结点,然后递归改变左右即可。记得递归边界。如果root的next不为空,证明root在这一层不是最后一个结点,所以root->next就是它的兄弟结点。将右子结点指向兄弟的左即可/*// Definitio..原创 2021-02-07 00:51:31 · 108 阅读 · 0 评论 -
108. 将有序数组转换为二叉搜索树
还以为手写avl,以前pat的时候手写avl轻轻松松,现在估计有点难其实就是二分递归建树,找到mid,用mid左边的序列来建左子树,mid右边来建右子树,mid用来创建当前结点。l>r才返回,=不返回。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val.原创 2021-02-07 00:46:33 · 102 阅读 · 0 评论 -
103. 二叉树的锯齿形层序遍历
来一个level记录当前是单数层还是奇数层就行,重点别把topNode写成root/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {.原创 2021-02-05 00:57:56 · 90 阅读 · 0 评论 -
617. 合并二叉树
全在t1上做修改,如果都为空就返回空,否则返回非空的。如果都不为空,就将t1的值改为两个结点相加,递归合并t1的左右,最后返回t1/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} *.原创 2021-01-31 01:41:07 · 64 阅读 · 0 评论 -
543. 二叉树的直径
和hard那题类似,记录左边和右边能提供给当前根结点的最大“半径”,res就和左+右比比看,然后返回的是左和右较大的那个+1。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * };.原创 2021-01-31 01:33:06 · 83 阅读 · 0 评论 -
538. 把二叉搜索树转换为累加树
累加树就是把大的结点递归加到小的上。因为是BST,所以右>根>左,维护一个cur也就是当前的累加值,用右根左的遍历方式即可。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) ...原创 2021-01-31 01:31:08 · 194 阅读 · 0 评论 -
437. 路径总和 III
传说中的双递归。因为可以从任意起点开始,所以先先序遍历,遍历到每个结点,对每个结点做dfs操作,将sum传进去即可,如果不是空结点,sum就减去当前结点的值,如果sum==0了,那么路径+1。但是 ==0后还不能直接返回!因为这里有负数,所以你再往下走,可能还能获得新的路/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode .原创 2021-01-30 01:17:22 · 104 阅读 · 0 评论 -
337. 打家劫舍 III
一开始递归,当前层和下一层只能偷一个。递归边界空结点,返回0。比较的是当前结点加上下下层和下一层哪个多,如果当前结点的左节点不为空,必须检查,不然对NULL指针做操作了。让当前结点的值+rob左子结点的左右结点+rob右子结点的左右结点。和rob左子结点+rob右子结点比。返回大的那一个。但是这样有大量的重复计算。比如偷当前结点的时候,要计算当前的孙子,计算当前结点的儿子时,儿子要计算儿子的儿子,也就是上一层的孙子,那就是重复计算了。我们用备忘录式递归,记录每个结点可以提供的最大的值,用map来记录,..原创 2021-01-29 10:07:03 · 81 阅读 · 0 评论 -
124. 二叉树中的最大路径和
hard就是hard。一定不要把题目想得过于复杂了,特别是树的问题,一定可以通过递归解决。这道题就是因为可以从任意结点作为起点,也不用走到叶子结点都算一条路径。其实你就是怕有负数罢了,我们在这里考虑每个根结点最大可以贡献多大的值,就算是根结点是-100,如果它的左右子结点中较大的那个可以贡献的数字大于100,那么根能贡献的总值还是个正数,可以取的。我们维护一个全局变量作为路径的最大值,也就是每次都进行判断当前结点作为中间结点的路径的总值和全局变量哪个大。递归边界就是到空结点,返回0,递归求左右子结点..原创 2021-01-28 00:38:47 · 148 阅读 · 0 评论 -
114. 二叉树展开为链表
最好用后序,方便理解,先一直往左,到达最左端结点之后一直往右,将这个结点的左子链加到右边去,记得记录下右子结点,然后遍历新的右子链,直到遍历到right为空,将原先记录的右子结点加到它下面。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(.原创 2021-01-27 01:43:32 · 68 阅读 · 0 评论 -
105. 从前序与中序遍历序列构造二叉树
第一次调用别越界!!是n-1不是n/** * 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(nullptr), ri.原创 2021-01-27 01:40:00 · 50 阅读 · 0 评论 -
102. 二叉树的层序遍历
在操作一个结点的时候将其加入tmp数组,每次while新建一个tmp数组,记录层次的层序遍历。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solut.原创 2021-01-27 01:39:13 · 59 阅读 · 1 评论 -
101. 对称二叉树
法一:一开始又是层序然后vector记录每一层再反转比较,但是不行,因为会有空结点,比如null,3,null,3这样反转的结果一样,但是不对称,所以null的地方用-1代替(不建议)法二:搞清楚每种情况,同时操作两个结点!!初始递归也是将左右同时入队。每次循环弹出两个top比较,三种情况,全为空,直接continue;一个为空一个不为空,false;两个值不等,false。接下来就是入队的顺序非常重要,左的左和右的右先入队,保证它俩等下一起比较,然后是左的右和右的左入队。法三:递归,也是同时操作两个.原创 2021-01-27 01:38:00 · 68 阅读 · 0 评论 -
98. 验证二叉搜索树
简单的判断每个根结点的左右结点的大小是错的,因为是bst我们应该考虑到bst的中序是从小到的,所以用数组记录中序然后判断是否有序或者用一个记录当前中序序列的最后一个值然后和下一个比较都可。迭代的话,也是用中序,用stack来模拟递归过程,左根右,先一直push左节点,然后取最左的结点,用一个数字来记录当前中序的最后即可/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNod.原创 2021-01-27 01:27:25 · 59 阅读 · 0 评论 -
96. 不同的二叉搜索树
一看就知道是数学题,两种方法,备忘录+dfs或者dp备忘录+dfs:当结点有0或者1的时候,就是一种情况,这是递归边界也是初始化dp数组的关键。https://leetcode-cn.com/problems/unique-binary-search-trees/solution/bu-tong-de-er-cha-sou-suo-shu-cong-yuan-shi-de-di-/https://leetcode-cn.com/problems/unique-binary-search-trees/.原创 2021-01-27 01:23:58 · 96 阅读 · 0 评论 -
94. 二叉树的中序遍历
其实递归也是用了系统栈,迭代只是显式地把栈表示出来。也是左根右的操作顺序非递归过程即:先访问…最左子树…结点,再访问其父节点,再访问其兄弟while循环条件 中序遍历需先判断当前结点是否存在,若存在则将该节点放入栈中,再将当前结点设置为结点的左孩子,若不存在则取栈顶元素为cur,当且仅当栈空cur也为空,循环结束。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNod.原创 2021-01-27 01:15:42 · 68 阅读 · 0 评论 -
297. 二叉树的序列化与反序列化
一顿操作猛如虎,一看超过5%两个操作都是dfs(前序遍历),序列化操作:因为是先序(根左右),所以先对根进行操作,如果为空就将字符串加上#并返回,因为要改变原字符串,所以传入的字符串是引用。如果不为空,就将string加上该结点值的字符串形式再加上’,’,然后递归左子树和右子树。反序列化操作:定义一个空结点,也是传引用,因为要改变自身的值,再传入输入的字符串和下标,因为不是char类型的字符串,所以不能通过++来取下一个要用下标取,所以index传的也是引用。如果index等于最后一位就return,.原创 2021-01-14 01:18:12 · 127 阅读 · 1 评论 -
236. 二叉树的最近公共祖先
lca算法,递归查询即可,如果当前结点为p或者q就返回当前结点,left等于取当前结点左子树查找的结果,right等于取右子树查找的结果,如果都不为l和r均不为空就返回root,如果左为空,那么就在右子树,就返回在右子树的查询结果即可(right),反之返回left/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *r..原创 2021-01-11 23:21:09 · 75 阅读 · 0 评论 -
226. 翻转二叉树
经典老题,bfs和dfs均可,记得判断是否为空就行/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public: Tree.原创 2021-01-11 23:17:27 · 63 阅读 · 0 评论