代码随想录算法日记day16 | 513.找树左下角的值、112. 路径总和、106.从中序与后序遍历序列构造二叉树

ops/2024/12/22 13:35:16/

原题链接&&讲解

222. 完全二叉树的节点个数
112. 路径总和
106.从中序与后序遍历序列构造二叉树
讲解>>代码随想录

222. 完全二叉树的节点个数

题目

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(从第 0 层开始),则该层包含 1~ 2h 个节点。

思路

法一:采用递归
法二:迭代

代码

java">// 递归
class Solution {public int countNodes(TreeNode root) {if(root == null) {return 0;}return countNodes(root.left) + countNodes(root.right) + 1;}
}
java">class Solution {// 迭代法深度优先搜索public int countNodes(TreeNode root) {if (root == null) {return 0;}Stack<TreeNode> stack = new Stack<>();stack.push(root);int result = 0;while (!stack.isEmpty()) {TreeNode node = stack.pop();result++; // 计数当前节点// 如果有右子节点,压入栈中if (node.right != null) {stack.push(node.right);}// 如果有左子节点,压入栈中if (node.left != null) {stack.push(node.left);}}return result;}
}
java">class Solution {// 迭代法深度优先搜索public int countNodes(TreeNode root) {if (root == null) {return 0;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int result = 0;while (!queue.isEmpty()) {int size = queue.size();while (size-- > 0) {TreeNode cur = queue.poll();result++;if (cur.left != null) queue.offer(cur.left);if (cur.right != null) queue.offer(cur.right);}}return result;}
}

112. 路径总和

题目

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

思路

DFS思路:
从根节点开始,沿着每一条路径向下遍历,直到找到一条路径满足所有节点值之和等于 targetSum 或者遍历完所有可能的路径。
BFS思路:拿层先来做显然不是很合适, 不过也可以去实现, 要多加一个队列来方便计算和

代码

java">class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {// 如果当前节点为空,返回falseif(root==null){return false;}// 否则,减去当前节点值targetSum -= root.val;// 检查是否为叶子节点并且路径和等于目标和if (root.left == null && root.right == null) {return targetSum == 0;}// 递归左右子树return hasPathSum(root.left, targetSum) || hasPathSum(root.right, targetSum);}
}
java">class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {if (root == null) {return false;}// 使用队列存储节点及其对应的路径和Queue<TreeNode> nodeQueue = new LinkedList<>();Queue<Integer> sumQueue = new LinkedList<>();nodeQueue.offer(root);sumQueue.offer(root.val);while (!nodeQueue.isEmpty()) {TreeNode currentNode = nodeQueue.poll();int currentSum = sumQueue.poll();// 检查是否为叶子节点并且路径和等于目标和if (currentNode.left == null && currentNode.right == null && currentSum == targetSum) {return true;}// 将左子节点及更新后的路径和加入队列if (currentNode.left != null) {nodeQueue.offer(currentNode.left);sumQueue.offer(currentSum + currentNode.left.val);}// 将右子节点及更新后的路径和加入队列if (currentNode.right != null) {nodeQueue.offer(currentNode.right);sumQueue.offer(currentSum + currentNode.right.val);}}return false;}
}

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

题目

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

思路

首先需要理解中序和后序遍历的含义, 这是必要的.

我们可以通过后序遍历的结果来确定根节点, 但是后序遍历无法确定根节点的左右子树
那么我们可以通过中序遍历来确定根节点的左右子树, 根节点已经在后序遍历中找到了.
就这样通过中序和后序遍历的配合, 我们可以逐个判断节点的位置, 将二叉树画出来.
那么接下来就是代码实现

步骤

  1. 确定根节点:
    后序遍历的最后一个元素是树的根节点。
  2. 分割左右子树:
    在中序遍历中找到根节点的位置,它左边的所有节点属于左子树,右边的所有节点属于右子树。
  3. 递归构造子树:
    根据中序遍历中根节点的位置,可以确定左右子树各自的中序和后序遍历序列。
    对于每个子树,重复步骤1和2的过程,即从后序遍历中找到子树的根节点,并在中序遍历中划分出更小的左右子树。
  4. 终止条件:
    当没有更多的节点用于构建子树时(即后序遍历或中序遍历为空),返回 null 表示当前递归分支结束。

代码

java">class Solution {private int postIndex;private HashMap<Integer, Integer> indexMap = new HashMap<>();public TreeNode buildTree(int[] inorder, int[] postorder) {if (inorder == null || postorder == null || inorder.length != postorder.length) {return null;}postIndex = postorder.length - 1;// 构建索引映射以获取中序序列中值到索引的快速查找int idx = 0;for (Integer val : inorder) {indexMap.put(val, idx++);}return buildTreeHelper(inorder, postorder, 0, inorder.length - 1);}private TreeNode buildTreeHelper(int[] inorder, int[] postorder, int inLeft, int inRight) {// 如果没有元素构造子树了,则返回nullif (inLeft > inRight) {return null;}// 选择 postIndex 位置元素作为当前子树根节点int rootValue = postorder[postIndex];TreeNode root = new TreeNode(rootValue);postIndex--;// 根据root所在中序的位置划分左右子树int index = indexMap.get(rootValue);// 先构造右子树,再构造左子树(因为后序遍历是“左->右->根”,所以从后往前)root.right = buildTreeHelper(inorder, postorder, index + 1, inRight);root.left = buildTreeHelper(inorder, postorder, inLeft, index - 1);return root;}
}

http://www.ppmy.cn/ops/144029.html

相关文章

MySQL数据库下载及安装教程

链接&#xff1a;MySQL数据库下载及安装教程&#xff08;最最新版&#xff09;_mysql下载安装-CSDN博客 亲测安装成功了&#x1f495; 把这个路径放到系统环境变量里头 MD!我这安到C盘去了&#xff0c;就很烦&#x1f92c;&#x1f621; 在CMD登录试一下 mysql -h localhos…

Flutter组合动画学习

如何使用动画控制器和动画来创建一个简单的动画效果。具体来说&#xff0c;它通过一个 AnimationController 来控制两个动画&#xff0c;一个用于旋转&#xff0c;一个用于绘制。 前置知识点学习 SingleTickerProviderStateMixin SingleTickerProviderStateMixin 是 Flutter …

wsl下Ubuntu(Linux)配置VSCode环境(C、C++)

一.vscode链接WSL 看我的另一篇博文&#xff1a; Vscode连接WSL2(Ubuntu20.04)_wsl2 vscode-CSDN博客 二.Linux系统配置c、c环境 和windows一样&#xff0c;要想使用C、C&#xff0c;要对系统环境进行配置&#xff0c;Linux是要安装gcc、g、gdb //可以用下面的代码在ubuntu…

uniapp实现手写签名,并在app中将其转为base64格式的图片

这里写自定义目录标题 1 手写签名页面&#xff1a;2 封装canvas组件&#xff1a;3 预览base64格式的签名图片&#xff1a; uniapp实现手写签名&#xff0c;并在app中将其转为base64格式的图片 1 手写签名页面&#xff1a; <template> <!-- 手写签名--><!-- &l…

基于 iAP2 协议 的指令协议,用于对安防设备的 MCU 进行操作

协议设计目标 1. 安全性&#xff1a;通过 iAP2 协议与 MCU 设备进行安全通信。 2. 通用性&#xff1a;支持对安防设备的常见功能进行操作&#xff0c;如状态查询、设备控制、参数配置等。 3. 高效性&#xff1a;数据结构简洁清晰&#xff0c;易于解析和扩展。 4. 扩展性&#x…

jenkins 出现 Jenkins: 403 No valid crumb was included in the request

文章目录 前言解决方式:1.跨站请求为找保护勾选"代理兼容"2.全局变量或者节点上添加环境变量3.&#xff08;可选&#xff09;下载插件 the strict Crumb Issuer plugin4.重启 前言 jenkins运行时间长了&#xff0c;经常出现点了好几次才能构建&#xff0c;然后报了Je…

【python】OpenCV—Image Moments

文章目录 1、功能描述2、图像矩3、代码实现4、效果展示5、完整代码6、涉及到的库函数cv2.moments 7、参考 1、功能描述 计算图像的矩&#xff0c;以质心为例 2、图像矩 什么叫图像的矩&#xff0c;在数字图像处理中有什么作用&#xff1f; - 谢博琛的回答 - 知乎 https://ww…

大模型技术优化负载均衡:AI驱动的智能化运维

在现代信息技术环境中&#xff0c;负载均衡是确保系统稳定、高效运行的关键技术。随着大模型技术&#xff08;Large Model Technology, LMT&#xff09;的发展&#xff0c;AI驱动的智能化负载均衡成为了优化系统性能、提升用户体验的重要手段。本文将详细介绍如何使用Python实现…