算法训练营day18

文章目录

        • 一、找树左下角的值
        • 二、路径总和1 & 2
          • 从路径总和1 & 2体会什么情况下递归需要返回值,什么时候不需要返回值
          • 路径总和1
          • 初始递归
          • DFS
          • BFS
          • 路径总和2
        • 三、从中序与后序遍历序列构造二叉树
        • 四、从前序和中序遍历序列构造二叉树

一、找树左下角的值

参考链接513. 找树左下角的值 - 力扣(LeetCode)

二叉树的最深最左侧的节点的值,涉及到最深 -> 联想到 层序遍历

BFS

class Solution {public int findBottomLeftValue(TreeNode root) {Deque<TreeNode> d = new ArrayDeque<>();d.addLast(root);int ans = 0;while (!d.isEmpty()) {int sz = d.size();ans = d.peek().val;while (sz-- > 0) {TreeNode poll = d.pollFirst();if (poll.left != null) d.addLast(poll.left);if (poll.right != null) d.addLast(poll.right);}}return ans;}
}

DFS

class Solution {int max, ans;public int findBottomLeftValue(TreeNode root) {dfs(root, 1);return ans;}void dfs(TreeNode root, int depth) {if (root == null) return ;if (depth > max) {max = depth; ans = root.val;}//左侧先执行dfs方法,如果最后一行存在多个节点,那么左侧的节点必定先执行//那么当执行到右侧的时候由于 depth == max,最先记录的永远是最左边的节点dfs(root.left, depth + 1);dfs(root.right, depth + 1);}
}
二、路径总和1 & 2
从路径总和1 & 2体会什么情况下递归需要返回值,什么时候不需要返回值
路径总和1
初始递归
   class Solution {public boolean hasPathSum(TreeNode root, int sum) {// 如果根节点为空,直接返回falseif (root == null) return false;// 如果当前节点是叶子节点(即左右子节点都为空),检查路径和是否等于目标值if (root.left == null && root.right == null) {return sum == root.val;}// 如果当前节点不是叶子节点,递归地在左子树和右子树中查找路径// 路径和等于目标值减去当前节点的值return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
DFS
  class Solution {
public boolean hasPathSum(TreeNode root, int sum) {// 如果根节点为空,直接返回falseif (root == null) return false;// 调用深度优先搜索(DFS)函数,查找是否存在一条从根节点到叶子节点的路径,使得路径上的节点值之和等于给定的目标值return dfs(root, sum, root.val);
}private boolean dfs(TreeNode root, int target, int pathSum) {// 如果当前节点为空,直接返回falseif (root == null) return false;// 如果路径和等于目标值,并且当前节点是叶子节点(即左右子节点都为空),返回trueif (pathSum == target && root.left == null && root.right == null) {return true;}// 初始化左右子树的标志位为falseboolean leftFlag = false, rightFlag = false;// 如果左子节点不为空,递归地在左子树中查找路径,路径和等于当前路径和加上左子节点的值if (root.left != null) {leftFlag = dfs(root.left, target, pathSum + root.left.val);}// 如果右子节点不为空,递归地在右子树中查找路径,路径和等于当前路径和加上右子节点的值if (root.right != null) {rightFlag = dfs(root.right, target, pathSum + root.right.val);}// 如果左子树或右子树中存在满足条件的路径,返回true,否则返回falsereturn leftFlag || rightFlag;
}
BFS
  class Solution {
public boolean hasPathSum(TreeNode root, int sum) {// 如果根节点为空,直接返回falseif (root == null) return false;// 创建一个队列,用于广度优先搜索(BFS)Deque<Pair<TreeNode, Integer>> queue = new LinkedList<>();// 将根节点和它的值作为一个对(Pair)添加到队列中queue.offer(new Pair<>(root, root.val));// 当队列不为空时,继续循环while (!queue.isEmpty()) {// 从队列中取出一个对Pair<TreeNode, Integer> pair = queue.poll();// 获取对中的节点和路径和TreeNode node = pair.getKey();int pathSum = pair.getValue();// 如果当前节点是叶子节点(即左右子节点都为空),并且路径和等于目标值,返回trueif (node.left == null && node.right == null && pathSum == sum) {return true;}// 如果左子节点不为空,将左子节点和当前路径和加上左子节点的值作为一个对添加到队列中if (node.left != null) {queue.offer(new Pair<>(node.left, pathSum + node.left.val));}// 如果右子节点不为空,将右子节点和当前路径和加上右子节点的值作为一个对添加到队列中if (node.right != null) {queue.offer(new Pair<>(node.right, pathSum + node.right.val));}}// 如果遍历完所有节点都没有找到满足条件的路径,返回falsereturn false;
}
路径总和2

参考链接113. 路径总和 II - 力扣(LeetCode)

先序遍历 + 路径记录

class Solution {LinkedList<List<Integer>> res = new LinkedList<>();LinkedList<Integer> path = new LinkedList<>();public List<List<Integer>> pathSum(TreeNode root, int targetSum) {recur(root, targetSum);return res;}void recur(TreeNode root, int tar) {if (root == null) return;path.add(root.val);tar -= root.val;if (tar == 0 && root.left == null && root.right == null)res.add(new LinkedList<Integer>(path));recur(root.left, tar);recur(root.right, tar);path.removeLast();}
}
三、从中序与后序遍历序列构造二叉树
class Solution {Map<Integer, Integer> map;  // 方便根据数值查找位置public TreeNode buildTree(int[] inorder, int[] postorder) {map = new HashMap<>();for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置map.put(inorder[i], i);}return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前闭后开}public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {// 参数里的范围都是前闭后开if (inBegin >= inEnd || postBegin >= postEnd) {  // 不满足左闭右开,说明没有元素,返回空树return null;}int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数root.left = findNode(inorder, inBegin, rootIndex,postorder, postBegin, postBegin + lenOfLeft);root.right = findNode(inorder, rootIndex + 1, inEnd,postorder, postBegin + lenOfLeft, postEnd - 1);return root;}
}
四、从前序和中序遍历序列构造二叉树

注,本文方法只适用于“无重复节点值”的二叉树。

为了提升效率,本文使用哈希表 dic 存储中序遍历的值与索引的映射,查找操作的时间复杂度为 O(1) 。

class Solution {int[] preorder;HashMap<Integer, Integer> dic = new HashMap<>();public TreeNode buildTree(int[] preorder, int[] inorder) {this.preorder = preorder;for(int i = 0; i < inorder.length; i++)dic.put(inorder[i], i);return recur(0, 0, inorder.length - 1);}TreeNode recur(int root, int left, int right) {if (left > right) return null;                          // 递归终止TreeNode node = new TreeNode(preorder[root]);          // 建立根节点int i = dic.get(preorder[root]);                       // 划分根节点、左子树、右子树node.left = recur(root + 1, left, i - 1);              // 开启左子树递归node.right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归return node;                                           // 回溯返回根节点}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/1138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运行python脚本下载官网安装包进行安装

背景介绍&#xff1a;1.由于公司业务人员window系统没有管理员用户权限&#xff0c;使用的是普通用户权限登陆的&#xff0c;因此不能自己安装软件。但是有时候涉及到软件的大批量更新&#xff0c;人工一个一个的去安装&#xff0c;效率太低&#xff0c;人工成本太高&#xff0…

DQ-DETR: DETR WITH DYNAMIC QUERY FOR TINY OBJECTDETECTION 学习笔记

论文地址&#xff1a;https://arxiv.org/pdf/2404.03507.pdf 此DQ-DETR与IDEA提出的同名&#xff0c;该文主要集中于小目标的检测 尽管之前的类似DETR的方法在通用目标检测中取得了成功&#xff0c;但在小目标检测方面仍然具有挑战性&#xff0c;因为目标 Query 的位置信息并未…

LWIP开启ARP之后进入硬件错误中断

遇到个很奇怪的问题&#xff0c;如下图只要开启ARP之后&#xff0c;就会进入硬件错误中断&#xff0c;关掉就好了。 而无法开启ARP&#xff0c;就不能ping 通&#xff0c;所以必须要解决这个问题。 最终debug发现死在memcpy函数位置 这样原因就很好分析了&#xff0c; 共4个拷…

通过linux工具iftop命令查看视频监控平台是否收到监控摄像头的视频流(视频监控平台接收和转发的视频流)

目录 一、需求描述 二、解决思路 &#xff08;一&#xff09;问题分析 &#xff08;二&#xff09;解决思路 1、通过抓包的方式 2、通过一些linux的网络监视工具 三、需求实现 &#xff08;一&#xff09;抓包工具 1、tcpdump 2、Wireshark 3、tcptrace &#xff0…

【刷题】 二分查找进阶

送给大家一句话&#xff1a; 你向神求助是因为相信神&#xff0c;神没有回应你是因为神相信你 ε≡٩(๑>₃<)۶ &#xfeff;ε≡٩(๑>₃<)۶ &#xfeff;ε≡٩(๑>₃<)۶ 一心向学 二分查找进阶 1 前言Leetcode 852. 山脉数组的峰顶索引题目描述算法思…

【EtherCAT】FMMU和SM简介

目录 一、简介 1、 FMMU 2、SM (1) 缓冲模式 (2)邮箱模式 3、FMMU将物理存储器映射到逻辑过程数据映射的配置原理 二、FMMU和SM在EtherCAT从站控制器的存储空间分配 三、FMMU和SM部分寄存器描述(LAN9253) 1、FMMU 2、SM 四、FMMU和SM的数据结构&#xff08;soem主站&…

什么是AIoT?

什么是AIoT? AIoT&#xff0c;即人工智能物联网&#xff0c;是一种将人工智能&#xff08;AI&#xff09;技术与物联网&#xff08;IoT&#xff09;相结合的新型应用形态。它不仅实现了设备之间的互联互通&#xff0c;还赋予了它们更智能化的特性。AIoT的核心在于通过AI的数据…

什么是知乎知+广告推广?

知乎作为中国领先的知识分享社区和高质量用户群体汇聚地&#xff0c;其广告价值日益凸显&#xff0c;其中&#xff0c;“知”作为知乎官方推出的创新广告形式&#xff0c;正逐渐成为品牌与消费者深度连接的重要桥梁。知广告推广不仅局限于传统意义上的硬性推广&#xff0c;更强…

解锁棋盘之谜:探索N皇后问题的全方位解决策略【python 力扣51题】

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

QML 中引用 js 文件闪退问题

问题描述 在移植 Android 中遇到这样一个引用兼容性问题&#xff0c;起因是这样的&#xff0c;Windows 版本的采用了 QML 分离的方式加载&#xff0c;而 Android 版本又采用了 qrc 的方式。而 Qt 中的机制是采用 QML 分离方式时则使用相对路径的方式引用 js 文件&#xff0c;而…

ZCMU 1531: 序列的混乱程度

Description 有一个长度为n的正整数序列&#xff0c;一个序列的混乱程度定义为这个序列的最大值和最小值之差。请编写一个程序&#xff0c;计算一个序列的混乱程度。 Input 输入的第一行为一个正整数T (T<1000)&#xff0c;表示一共有T组测试数据。 每组测试数据的第一行为一…

前后端跨域请求代码实战(vue3.4+springboot2.7.18)

前端代码 v3.4.21&#xff08;前端不是主业&#xff0c;所以就贴一贴代码&#xff0c;有疑问评论区见&#xff09;后端代码&#xff0c;springboot 2.7.18&#xff08;后端&#xff09; 文章内容&#xff1a; 一&#xff0c;后端代码 二&#xff0c;前端代码 三&#xff0c;后…

【ARM 裸机】I.MX 启动方式之启动头文件 1

接上一节&#xff1a;【ARM 裸机】I.MX 启动方式之启动设备的选择&#xff1b; 2、启动头文件 当 BOOT_MODE1 为 1&#xff0c;BOOT_MODE0 为 0 的时候此内部 BOOT 模式&#xff0c;在此模式下&#xff0c;芯片会执 行内部的 BOOT ROM 代码&#xff0c;这段 BOOT ROM 代码会进…

C++引用和指针的区别

在C中&#xff0c;引用和指针都是用于间接访问变量或对象的工具&#xff0c;但它们之间存在一些重要的区别。 引用&#xff08;Reference&#xff09; 引用是变量的别名&#xff0c;它提供了一个已经存在的变量的另一个名字。一旦一个引用被初始化为一个对象&#xff0c;就不…

tensor是pytorch的核心,那torch.tensor和torch.Tensor区别是?

本文重点 从本节课程开始我们将正式开启pytorch的学习了&#xff0c;在深度学习框架中有一个重要的概念叫做张量&#xff0c;它是pytorch的基本操作单位&#xff0c;要想创建tensor有很多的方式&#xff0c;但是有两个torch.tensor和torch.Tensor容易混淆&#xff0c;本节课程…

javase__进阶 day13stream流和方法引用

1.不可变集合 1.1 什么是不可变集合 ​ 是一个长度不可变&#xff0c;内容也无法修改的集合 1.2 使用场景 ​ 如果某个数据不能被修改&#xff0c;把它防御性地拷贝到不可变集合中是个很好的实践。 ​ 当集合对象被不可信的库调用时&#xff0c;不可变形式是安全的。 简单…

docker快速使用简介

进入服务器 ssh root192.0.0.211安装 docker load < bevformer_image.tar修改镜像的REPOSITORY和TAG docker tag a6a4c15ca9db bevformer:1.0其中&#xff0c;a6a4c15ca9db是原来镜像的id。bevformer是修改后的REPOSITORY&#xff1b;1.0是修改后的TAG。 从Docker Hub上…

高精度加减乘除

高精度加法 题目链接&#xff1a;高精度加法 #include <bits/stdc.h> #define int long long using namespace std; const int N 1e55; int a[N],b[N]; int c[N]; int n,m; string s1,s2;signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>s1…

大厂面试精华面试刷题

1.自定义unshift实现相同效果 2.数组去重 用vs2019来写这种练习题可以更直观的查看代码执行的效果&#xff0c;最后的代码是控制控制台执行完毕后不自动关闭 use strict;let arr [1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] //1.//查重最简单的方法for循环结合splice从数组中…

Flask vs FastApi 性能对比测试

Flask和Fastapi都是Python下流行的Web框架&#xff0c;前者有大量拥趸&#xff0c;是一个老牌框架&#xff0c;后者相对较新&#xff0c;但是利用了异步技术和uvloop&#xff0c;都说性能比Flask好很多&#xff0c;于是就我就对比实测一下。由于Windows下不支持uvloop&#xff…