当前位置: 首页 > news >正文

代码随想录算法训练营第17天(二叉树5)| 找树左下角的值二叉树的路径总和从中序与后序遍历序列构造二叉树从前序与中序遍历序列构造二叉树

513.找树左下角的值

leetcode题目地址
题目链接/文章讲解/视频讲解

如果使用递归法,如何判断是最后一行:
其实就是深度最大的叶子节点一定是最后一行。

//迭代法
class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);int result = 0;while (!que.empty()) {int size = que.size();for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();if (i == 0) result = node->val; // 记录最后一行第一个元素if (node->left) que.push(node->left);if (node->right) que.push(node->right);}}return result;}
};//递归法
class Solution {
public:int maxDepth = INT_MIN;int result;void traversal(TreeNode* root, int depth) {if (root->left == NULL && root->right == NULL) {if (depth > maxDepth) {maxDepth = depth;result = root->val;}return;}if (root->left) {traversal(root->left, depth + 1); // 隐藏着回溯,下一个遍历的时候深度加一,本层的不变}if (root->right) {traversal(root->right, depth + 1); // 隐藏着回溯, 下一个遍历的时候深度加一,本层的不变}return;}int findBottomLeftValue(TreeNode* root) {traversal(root, 0);return result;}
};

112. 路径总和

leetcodet题目链接
题目链接/文章讲解/视频讲解
因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。
递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。
左右子树递归时候的返回值要做判断,如果有一支返回true就可以提前返回结果,如果都没有返回true,返回false

class Solution {
private:bool traversal(TreeNode* cur, int count) {if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回if (cur->left) { // 左count -= cur->left->val; // 递归,处理节点;if (traversal(cur->left, count)) return true;// 提前结束递归count += cur->left->val; // 回溯,撤销处理结果}if (cur->right) { // 右count -= cur->right->val; // 递归,处理节点;if (traversal(cur->right, count)) return true;// 提前结束递归count += cur->right->val; // 回溯,撤销处理结果}return false;}public:bool hasPathSum(TreeNode* root, int sum) {if (root == NULL) return false;return traversal(root, sum - root->val);}
};

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

106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树
leetcode题目链接
题目链接/文章讲解/视频讲解
说到一层一层切割,就应该想到了递归。
来看一下一共分几步:
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间

//框架代码
TreeNode* traversal (vector<int>& inorder, vector<int>& postorder) {// 第一步if (postorder.size() == 0) return NULL;// 第二步:后序遍历数组最后一个元素,就是当前的中间节点int rootValue = postorder[postorder.size() - 1];TreeNode* root = new TreeNode(rootValue);// 叶子节点if (postorder.size() == 1) return root;// 第三步:找切割点int delimiterIndex;for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break;}// 第四步:切割中序数组,得到 中序左数组和中序右数组// 第五步:切割后序数组,得到 后序左数组和后序右数组// 第六步root->left = traversal(中序左数组, 后序左数组);root->right = traversal(中序右数组, 后序右数组);return root;
}//完整代码
class Solution {
private:TreeNode* traversal (vector<int>& inorder, vector<int>& postorder) {if (postorder.size() == 0) return NULL;// 后序遍历数组最后一个元素,就是当前的中间节点int rootValue = postorder[postorder.size() - 1];TreeNode* root = new TreeNode(rootValue);// 叶子节点if (postorder.size() == 1) return root;// 找到中序遍历的切割点int delimiterIndex;for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break;}// 切割中序数组// 左闭右开区间:[0, delimiterIndex)vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);// [delimiterIndex + 1, end)vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );// postorder 舍弃末尾元素postorder.resize(postorder.size() - 1);// 切割后序数组// 依然左闭右开,注意这里使用了左中序数组大小作为切割点// [0, leftInorder.size)vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());// [leftInorder.size(), end)vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());root->left = traversal(leftInorder, leftPostorder);root->right = traversal(rightInorder, rightPostorder);return root;}
public:TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if (inorder.size() == 0 || postorder.size() == 0) return NULL;return traversal(inorder, postorder);}
};
http://www.lryc.cn/news/290747.html

相关文章:

  • 代码随想录 Leetcode106. 从中序与后序遍历序列构造二叉树
  • Log4j Log4j2
  • C语言——如何进行文件操作
  • python中for循环的几个现象
  • openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板
  • Delphi.cz采访​Embarcadero​捷克共和国办事处经理:理查德·库巴特 - 第一部分
  • AI投资或成科技裁员罪魁祸首
  • 解读BEVFormer,新一代自动驾驶视觉工作的基石
  • 【React教程】(1) React简介、React核心概念、React初始化
  • 云计算中的弹性是什么?
  • Vue3基础:pnpm是什么?npm和pnpm的区别?如何使用pnpm?
  • vue中父组件直接调用子组件方法(通过ref)
  • Gunicorn性能优化:提升Python Web应用的服务效率
  • 如何使用ssh key免密码登录服务器?
  • macos Android平台签名证书(.keystore)
  • Kotlin快速入门系列2
  • 单片机之keil软件环境搭建
  • 数学公式OCR识别php 对接mathpix api 使用公式编译器
  • MySQL原理(二)存储引擎(1)概述
  • 微信小程序canvas画布如何解决在for循环绘制图像显示不全的问题
  • Python计算机二级/Python期末考试 刷题(一)
  • 最新GPT4.0使用教程,AI绘画-Midjourney绘画,GPT语音对话使用,DALL-E3文生图+思维导图一站式解决
  • 【JavaScript】两种方法实现继承
  • 张维迎《博弈与社会》笔记(3)导论:一些经济学的基础知识
  • 随机生成UI不重叠
  • 【C/C++】C/C++编程——第一个 C++ 程序:HelloWorld
  • 扩散视觉反事实算法 DVC:对抗性鲁棒分类器 + 扩散模型,跨模态对比原始的 fundus 图 VS 生成的 OCT 图
  • C++(6) 继承
  • 【Servlet】Smart Tomcat插件简化Servlet开发流程及解决常见问题
  • 解决Qt连接不上mysql数据库