首页 > 编程语言 >代码随想录算法训练营第十八天| 513.找树左下角的值 112. 路径总和 106.从中序与后序遍历序列构造二叉树

代码随想录算法训练营第十八天| 513.找树左下角的值 112. 路径总和 106.从中序与后序遍历序列构造二叉树

时间:2023-08-17 10:44:04浏览次数:40  
标签:第十八天 return cur 随想录 traversal 二叉树 root 节点 postorder

 

找树左下角的值  

     卡哥建议:本地递归偏难,反而迭代简单属于模板题, 两种方法掌握一下 

    题目链接/文章讲解/视频讲解:https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html

     做题思路:

     题目说在树的最后一行找到最左边的值。深度最大的叶子节点一定是最后一行。所以要找深度最大的叶子节点。注意:最左边的值不一定是左叶子节点,如果没有左叶子节点,只有右叶子节点的话,那右叶子节点就是最左边的值。

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

    那么如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。     

    在找最大深度的时候,递归的过程中依然要使用回溯,左子树找完了,再去右子树找。

    迭代法看卡哥文章。

     本题代码:

 1 class Solution {
 2 public:
 3     int maxDepth = INT_MIN; //int 的最小值
 4     int result;
 5     void traversal(TreeNode* root, int depth) {
 6         if (root->left == NULL && root->right == NULL) {
 7             if (depth > maxDepth) {
 8                 maxDepth = depth;
 9                 result = root->val;
10             }
11             return;
12         }
13         if (root->left) {
14             depth++;
15             traversal(root->left, depth);
16             depth--; // 回溯
17         }
18         if (root->right) {
19             depth++;
20             traversal(root->right, depth);
21             depth--; // 回溯
22         }
23         return;
24     }
25     int findBottomLeftValue(TreeNode* root) {
26         traversal(root, 0);
27         return result;
28     }
29 };

 

路径总和  

     卡哥建议:本题 又一次设计要回溯的过程,而且回溯的过程隐藏的还挺深,建议先看视频来理解 ,112. 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。

    题目链接/文章讲解/视频讲解:https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html

     做题思路:

     需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。如果遍历到了叶子节点,count不为0,就是没找到。回溯部分在递归完了,再重新让计数器加回值。

   本题代码: 

 1 class Solution {
 2 private:
 3     bool traversal(TreeNode* cur, int count) {
 4         if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
 5         if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回
 6 
 7         if (cur->left) { // 左
 8             count -= cur->left->val; // 递归,处理节点;
 9             if (traversal(cur->left, count)) return true;
10             count += cur->left->val; // 回溯,撤销处理结果
11         }
12         if (cur->right) { // 右
13             count -= cur->right->val; // 递归,处理节点;
14             if (traversal(cur->right, count)) return true;
15             count += cur->right->val; // 回溯,撤销处理结果
16         }
17         return false;
18     }
19 
20 public:
21     bool hasPathSum(TreeNode* root, int sum) {
22         if (root == NULL) return false;
23         return traversal(root, sum - root->val);
24     }
25 };

 

 从中序与后序遍历序列构造二叉树 

     卡哥建议:本题算是比较难的二叉树题目了,大家先看视频来理解。 106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的

    题目链接/文章讲解/视频讲解:https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html

     做题思路:

      这里的思路看卡哥视频和文章吧。

    中序:左中右

    后序:左右中

     本题代码:

 1 class Solution {
 2 private:
 3     TreeNode* traversal (vector<int>& inorder, vector<int>& postorder) {
 4         if (postorder.size() == 0) return NULL;//后序里没有根节点
 5 
 6         // 后序遍历数组最后一个元素,就是当前的中间节点
 7         int rootValue = postorder[postorder.size() - 1];
 8         TreeNode* root = new TreeNode(rootValue);//得到一个根子节点
 9 
10         // 叶子节点
11         if (postorder.size() == 1) return root;
12 
13         // 找到中序遍历的切割点
14         int delimiterIndex;
15         for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
16             if (inorder[delimiterIndex] == rootValue) break; //从后序得到的根节点,再到中序里找根节点,进行切割
17         }
18 
19         // 切割中序数组
20         // 左闭右开区间:[0, delimiterIndex),切的左边是含有切割点的,右边是不含有切割点的
21         vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
22         // [delimiterIndex + 1, end)
23         vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );
24 
25         // postorder 舍弃末尾元素
26         postorder.resize(postorder.size() - 1);
27 
28         // 切割后序数组
29         // 依然左闭右开,注意这里使用了左中序数组大小作为切割点
30         // [0, leftInorder.size)
31         vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());//这里画图理解吧
32         // [leftInorder.size(), end)
33         vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
34 
35         root->left = traversal(leftInorder, leftPostorder);
36         root->right = traversal(rightInorder, rightPostorder);
37 
38         return root;
39     }
40 public:
41     TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
42         if (inorder.size() == 0 || postorder.size() == 0) return NULL;
43         return traversal(inorder, postorder);
44     }
45 };

 

 

 

标签:第十八天,return,cur,随想录,traversal,二叉树,root,节点,postorder
From: https://www.cnblogs.com/romantichuaner/p/17636805.html

相关文章

  • 代码随想录算法训练营第十七天| 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子
     卡哥建议:迭代法,大家可以直接过,二刷有精力的时候 再去掌握迭代法。  110.平衡二叉树 (优先掌握递归)   卡哥建议:再一次涉及到,什么是高度,什么是深度,可以巩固一下。   题目链接/文章讲解/视频讲解:https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%......
  • 【剑指Offer】58、对称的二叉树
    【剑指Offer】58、对称的二叉树题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。解题思路:本题判断一棵树是不是对称的,和第18题可以对比分析:二叉树的镜像,和LeetCode第101题:101.对称二叉树是同一道题。解......
  • 【剑指Offer】59、按之字形顺序打印二叉树
    【剑指Offer】59、按之字形顺序打印二叉树题目描述:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。解题思路:这道题仍然是二叉树的遍历,相当于层次遍历,可以和第22题:从上往下打印二......
  • 剑指 Offer 37. 序列化二叉树(困难)
    题目:classCodec{public:voidrserialize(TreeNode*root,string&str){//编码递归函数:将树按照前序遍历,放入str字符串中。每个节点元素用','分隔if(root==nullptr){//如果遇到空节点,写入"none"。str+="none,";}el......
  • [代码随想录]Day19-二叉树part08
    题目:235.二叉搜索树的最近公共祖先思路:BST和普通二叉树不同的一点是可以根据特性来找最近公共祖先,只要找到第一个值比p大比q小(假设p<q)的节点返回即可。代码:/***Definitionforabinarytreenode.*typeTreeNodestruct{*Valint*Left*TreeNode......
  • 【剑指Offer】38、二叉树的深度
    题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。解题思路:本题相对比较简单。根据二叉树深度的定义,我们有以下理解:如果一棵树只有一个结点,那么它的深度为1。如果根结点只有左子树而没有右子树,那么......
  • 代码随想录算法训练营第十三天|单调数列:滑动窗口最大值(力扣239.)、优先级队列:前k个高
    单调数列:滑动窗口最大值(力扣239.)给定滑动窗口的范围,求每个滑动窗口范围内的最大值使用单调队列实现对于最大值数字前面的数字不存入数列,对于最大值数字后面的数字存入数列中单调队列中数字的大小呈递减顺序pop(value):如果窗口移除的元素等于单调队列的队口元素,则pop;否则什......
  • [代码随想录]Day18-二叉树part07
    题目:530.二叉搜索树的最小绝对差思路:一个关键问题——BST的中序遍历是由小到大的顺序,也就是说记录遍历的前一个节点,每次比较当前节点-前一个节点的值即可(因为由小到大所以当前>前一个)代码:/***Definitionforabinarytreenode.*typeTreeNodestruct{*Val......
  • 代码随想录算法训练营第十一天|力扣20.有效的括号、力扣1047.删除字符串中所有相邻重
    有效的括号(力扣20.)括号匹配时使用栈解决的经典问题题意其实就像我们在写代码的过程中,要求括号的顺序是一样的有左括号,那么在对应位置则必须有右括号第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以returnfalse第二种情况:遍历字......
  • 二叉树:自下而上,从左到右的层次遍历
    利用栈先进后出的特性,将出队元素依次进栈,然后依次出栈即可完成。#include<stdio.h>#include<stdlib.h>#defineMaxSize100//二叉树的结点类型typedefstructNode{intdata;structNode*lchild,*rchild;}TreeNode,*Tree;//队列的结点类型typedefstru......