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

代码随想录刷题笔记 DAY 18 | 找树左下角的值 No.513 | 路经总和 No.112 | 从中序与后序遍历序列构造二叉树 No.106

Day 18

01. 找树左下角的值(No. 513)

题目链接

代码随想录题解

1.1 题目

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入: root = [2,1,3]
输出: 1

示例 2:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7

提示:

  • 二叉树的节点个数的范围是 [1,104]
  • -231 <= Node.val <= 231 - 1
1.2 笔记

这道题递归实现很简单,但思路是比较难想到

根据这个题目中的 最底层 可以得到,无论是收集到的上一个节点多么靠左,如果有比它还深的节点,那这个节点更有可能是结果的节点。

比如上图中,无论 1 节点多么靠左,这道题的答案仍然是 6,这也就导致了 最左边的节点不一定是左节点,递归向左的方式就被否定了。

但如果是同层的,因为采用的遍历顺序是 左中右 的顺序,同层的最左边一定是被最先遍历到的,所以对于同层的只需要拿到第一个即可。

这里定义一个类来存放节点的 深度数值

class Node {int val;int floor;public Node(int val, int floor) {this.val = val;this.floor = floor;}
}
1.3 代码
class Solution {int floor = 0; // 记录当前节点的层数Node tempNode = new Node(0, 0);public int findBottomLeftValue(TreeNode root) {tempNode = new Node(root.val, 1);reverse(root);return tempNode.val;}public void reverse(TreeNode node) {if (node == null) {return;}floor++;// 说明本次遍历到的节点深度更深if (floor > tempNode.floor) {tempNode = new Node(node.val, floor);}reverse(node.left);reverse(node.right);floor--;}
}
/**记录可能是结果的节点的深度和值*/
class Node {int val;int floor;public Node(int val, int floor) {this.val = val;this.floor = floor;}
}

02. 路经总和(No. 112)

题目链接

代码随想录题解

2.1 题目

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

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

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

提示:

  • 树中节点的数目在范围 [0, 5000]
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000
2.2 笔记

是一道非常简单的递归题目,和递归计算深度思路完全相同,但是本题计算的是总和。

但这道题目有一个很大的坑就是在剪枝上,剪枝到最后发现最好的方式是不要加任何剪枝操作

看一下能想到的剪枝的想法

  • 当前总和大于目标值:推翻,因为有可能存在负数
  • 当目标值大于 0 时选大于,小于 0 时选小于:推翻,因为节点中可能存在负数

所以本题是无法加入剪枝操作的,对这些边缘处理一定要考虑好。

剩下的就是简单的递归处理了。

为了递归代码尽量的简洁,我将 targetSum 单独的抽离出来作为一个全局变量。

这道题在回顾一下递归要考虑的三个部分

  • 递归的出口:node = null 因为对空节点的任何操作都是没有意义的,还有就是叶子节点,在叶子节点直接收集信息然后可以返回,直接返回的话要进行后续位置进行的操作,这里再详细的解释一下,看下面代码中判断叶子节点并且返回的位置,这个位置处于递归的前序位置,但是 currentSum -= node.val 是处于后序位置的,也就是说后续位置的操作还没有执行就直接返回了;当然,也可以选择不 return,递归到下一层发现是空节点返回后同样也会执行后序位置的代码。
  • 递归的返回值:因为这里采用外置全局变量的方式,是不需要任何返回值的。
  • 递归中要进行的操作:拿取当前路径下的总和、判断是否符合结果的要求,分别向左向右递归,离开节点时删除节点的 val
2.3 代码
class Solution {int currentSum = 0; // 记录总和boolean flg = false;int target;public boolean hasPathSum(TreeNode root, int targetSum) {target = targetSum;reverse(root);return flg;}public void reverse(TreeNode node) {if (node == null) {return;}currentSum += node.val;// 判断是否为叶子节点if (currentSum == target && node.right == null && node.left == null) {flg = true;return;}reverse(node.right);reverse(node.left);currentSum -= node.val;}
}

03. 从中序与后序遍历序列构造二叉树(No. 106)

题目链接

代码随想录题解

1.1 题目

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

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

示例 2:

输入:inorder = [-1], postorder = [-1]
输出:[-1]

提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorderpostorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历
1.2 笔记

后序遍历的顺序是 左 右 中

中序遍历的顺序是 左 中 右

先来看一下为什么仅仅通过一个遍历得不到完整的二叉树,而需要两个遍历配合

这就导致了这两种遍历形成的数组是这样的:

后序的最后一个位置的节点一定是中心节点,但是这个节点的左子树和右子树是混合在左边的,再来看中序遍历,虽然它的左右子树是分开的,但是中心节点不得而知,所以需要两个遍历顺序配合来解题。

通过上面的规律,可以总结出一个大概的解题思路:

  1. 从后序拿到中心节点
  2. 在中序中找到中心节点
  3. 分割中序数组,可以得到左子树的所有节点和右子树的所有节点
  4. 通过分割完成的两个中序数组的长度来切割后序的数组
  5. 构造当前的节点,也就是后序的最后一个元素
  6. 以新的中序数组和新的后序数组再次执行上述的步骤,直到只剩下一个节点

这个思路就需要通过递归来完成

简单的画一个图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过这样逐次的递归,会在后序数组和中序数组长度为 1 的时候就是递归结束的时候,这时候创建节点直接返回即可

再来看每次递归中要做的事情:

  • 递归的出口,数组为 null 也就是传入数据为空的时候直接返回空;当数组的长度为 1 的时候,比如上图的 9 节点,意味着遍历到叶子节点了,这时候也直接返回。
  • 递归返回值:因为要构建二叉树,返回的内容是一个节点,使得返回的这个节点树称为上一个节点的子树。
  • 每次递归要进行的内容:判断是否符合返回条件、执行上面的六个步骤、返回该节点
3.3 代码
class Solution {public TreeNode buildTree(int[] inorder, int[] postorder) {return reverse(inorder, postorder);}public TreeNode reverse(int[] inorder, int[] postorder) {if (postorder.length == 0) {return null;}if (postorder.length == 1) {// 叶子节点return new TreeNode(postorder[0]);}int target = postorder[postorder.length - 1]; // 拿到节点的值int index = 0;for (int i = 0; i < inorder.length; i++) {if (inorder[i] == target) {index = i; // 记录切割节点的值break;}}// 切割中序数组,copyOfRange 为左闭右开int[] newInorderLeft = Arrays.copyOfRange(inorder, 0, index); // 左int[] newInorderRight = Arrays.copyOfRange(inorder, index + 1, inorder.length); // 右// 切割后序数组int[] newPostorderLeft = Arrays.copyOfRange(postorder, 0, newInorderLeft.length);int[] newPostorderRight = Arrays.copyOfRange(postorder, newInorderLeft.length, postorder.length-1);TreeNode node = new TreeNode(target);node.left = reverse(newInorderLeft, newPostorderLeft);node.right = reverse(newInorderRight, newPostorderRight);return node;
3.4 补充

上述的代码中不断的进行数组的切割,会导致时间复杂度很高,这里可以使用逻辑切割,也就是通过传入数组的 startIndexendIndex 来限制数组的空间。

这时候递归的出口就变成了

startIndex == endIndex || startIndex > endIndex

后一个条件是为了处理空的情况,如果带入空值会让数组下标出现负数,可以调试试一下

还需要修改的是下面传入的内容,书写的时候可以把当前的数组写出来,比如起始位置不要写 0 而要写 startIndex,这样可以避免书写条件的时候出错

node.left = reverse(inorderStart, index-1, postorderStart, postorderStart+(index- inorderStart-1));
node.right = reverse(index+1, inorderEnd, postorderStart+(index-inorderStart), postorderEnd-1);

最终写出的条件是这样的,总体的思路和上面的代码相同

class Solution {int[] globalInorder;int[] globalPostOrder;public TreeNode buildTree(int[] inorder, int[] postorder) {globalInorder = inorder;globalPostOrder = postorder;return reverse(0, inorder.length-1, 0, postorder.length-1);}public TreeNode reverse(int inorderStart, int inorderEnd, int postorderStart, int postorderEnd) {if (postorderStart > postorderEnd) {return null;}if (postorderEnd == postorderStart) {// 叶子节点return new TreeNode(globalPostOrder[postorderStart]);}int target = globalPostOrder[postorderEnd]; // 拿到节点的值int index = 0;for (int i = inorderStart; i <= inorderEnd; i++) {if (globalInorder[i] == target) {index = i; // 记录切割节点的值,也就是此时的节点break;}}TreeNode node = new TreeNode(target);node.left = reverse(inorderStart, index-1, postorderStart, postorderStart+(index-inorderStart-1));node.right = reverse(index+1, inorderEnd, postorderStart+(index-inorderStart), postorderEnd-1);return node;}
}

相关文章:

代码随想录刷题笔记 DAY 18 | 找树左下角的值 No.513 | 路经总和 No.112 | 从中序与后序遍历序列构造二叉树 No.106

Day 18 01. 找树左下角的值&#xff08;No. 513&#xff09; 题目链接 代码随想录题解 1.1 题目 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 示例 2: 输入…...

【algorithm】一个简单的PID工程 base 用于手生时候快速复习 用于设计模式 cpp语法八股 快速复习校验

写在前面 最近项目一直用matlab&#xff0c;防止手生整一个回忆工具使用的简单的pid demo&#xff0c;走一边流程&#xff0c;包括配工程debug看结果&#xff0c;复用之前记录的配置见我的bloghttps://blog.csdn.net/weixin_46479223/article/details/135082867?csdn_share_t…...

Python处理图片生成天际线(2024.1.29)

1、天际线简介 天际线&#xff08;SkyLine&#xff09;顾名思义就是天空与地面的边界线&#xff0c;人站在不同的高度&#xff0c;会看到不同的景色和地平线&#xff0c;天空与地面建筑物分离的标记线&#xff0c;不得不说&#xff0c;每天抬头仰望天空&#xff0c;相信大家都可…...

jsp服装穿搭推荐系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 游戏网上商城系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…...

Opencv(C++)学习 之RV1126平台的OPENCV交叉编译

本文特点&#xff1a;网上已经有了很多opencv移植RV1106的文章&#xff0c;本文主要记录基于cmake-gui编译&#xff0c;碰到的报错&#xff0c;及解决报错问题的方法&#xff0c;同时简单总结一些配置项相关的知识。 一、环境&#xff1a; ubuntu18 x64 RV1126交叉编译工具链 …...

http和https区别

HTTP协议以明文方式发送内容&#xff0c;不提供任何方式的数据加密。HTTP协议不适合传输一些敏感信息&#xff0c;比如&#xff1a;信用卡号、密码等支付信息。https则是具有安全性的ssl加密传输协议。http和https使用的是完全不同的连接方式&#xff0c;用的端口也不一样&…...

富文本编辑器CKEditor4简单使用-05(开发自定义插件入门)

富文本编辑器CKEditor4简单使用-05&#xff08;开发自定义插件入门&#xff09; 1. CKEditor4插件入门1.1 关于CKEditor4插件的简单安装与使用1.2 参考 2. 开发自定义插件——当前时间插件2.1 创建插件文件目录结构2.2 编写插件原代码2.2.1 编写代码框架2.2.2 创建编辑器命令2.…...

chisel之scala 语法

Chisel新手教程之Scala语言&#xff08;1&#xff09; Value & variable Value是immutable的&#xff0c;当它被分配一个数据后&#xff0c;无法进行重新分配。用 val 表示。 Variable是mutable的&#xff0c;可以重复赋值。用 var 表示。示例如下&#xff1a; val a …...

React18构建Vite+Electron项目以及打包

一.先创建项目 cnpm create vite 选择React > JavaScript >cd react_vite > cnpm i >npm run dev 二.安装Electron依赖 指定版本相对稳定 cnpm i electron19.0.10 -D cnpm i vite-plugin-electron0.9.3 -D cnpm i electron-builder23.0.1 -D三.创建electron目录…...

Spark性能调优

Spark性能调优 executor内存不足用UNION ALL代替UNIONpersist与耗时监控用OR替换UNION ALL用JOIN替换IN executor内存不足 问题表现1&#xff1a;Container xx is running beyond physical memory limits. Current usage: xxx GB of x GB physical memory used; xx GB of x GB…...

flutter开发实战-Camera自定义相机拍照功能实现

flutter开发实战-Camera自定义相机拍照功能实现 一、前言 在项目中使用image_picker插件时候&#xff0c;在android设备上使用无法默认设置前置摄像头&#xff08;暂时不清楚什么原因&#xff09;&#xff0c;由于项目默认需要使用前置摄像头&#xff0c;所以最终采用自定义…...

LeetCode15. 三数之和

15. 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 **注意&#xff1a;**答案中不可以包含重复…...

Docker搭建MySQL8主从复制

之前文章我们了解了面试官&#xff1a;说一说Binlog是怎么实现的&#xff0c;这里我们用Docker搭建主从复制环境。 docker安装主从MySQL 这里我们使用MySQL8.0.32版本&#xff1a; 主库配置 master.cnf //基础配置 [client] port3306 socket/var/run/mysqld/mysql.sock [m…...

【前端】日期转换

记录项目中需要处理的日期格式 默认vue2 初级版 将后端传来的数组 [2024/01/29 08:55:18, 2024/01/29 09:55:18, 2024/01/29 10:11:18]转为 [2024-01-29 08:55, 2024-01-29 09:55, 2024-01-29 10:11]方法 convertDateTimeFormat(arr) {var tempArr arr.map(function (dateT…...

Git 怎么设置用户的权限

在团队协作的软件开发中&#xff0c;对于版本控制系统Git来说&#xff0c;确保代码与数据的安全性至关重要。为了实现这一目标&#xff0c;Git提供了灵活且可定制的用户权限管理机制。下面将简单的探讨一下Git如何设置用户的权限&#xff0c;以及如何保护代码和数据。 用户身份…...

大端和小端模式介绍

介绍 “大端”和“小端”通常指的是字节序&#xff08;Byte Order&#xff09;的两种类型&#xff0c;也被称为端序&#xff08;Endianness&#xff09;。在多字节的数据类型&#xff08;如整数&#xff09;中&#xff0c;字节可以以不同的顺序存储&#xff0c;这影响了计算机…...

【vue】报错 Duplicate keys detected 解决方案

错误描述&#xff1a;Duplicate keys detected. This may cause an update error.错误直译&#xff1a;检测到重复的键。这可能会导致错误。错误原因&#xff1a;有相同父元素的多个子元素的v-for有相同的key值。 解决方法&#xff1a; return:{dataList:[{name:张三&#xf…...

机器学习_13_SVM支持向量机、感知器模型

文章目录 1 感知器模型1.1 感知器的思想1.2 感知器模型构建1.3 损失函数构建、求解 2 SVM3 线性可分SVM3.1 线性可分SVM—概念3.2 线性可分SVM —SVM 模型公式表示3.3 线性可分SVM —SVM 损失函数3.4 优化函数求解3.5 线性可分SVM—算法流程3.6 线性可分SVM—案例3.7 线性可分S…...

OpenCV学习记录——轮廓检测

文章目录 前言一、寻找、绘制轮廓二、具体应用代码 前言 寻找目标图像的轮廓并绘制出该轮廓是我们进行图像识别时常用的手段&#xff0c;轮廓是图像中连续的边界线&#xff0c;可以用于物体检测、形状分析等应用。为了获取更高的准确性&#xff0c;会先进行二值化处理&#xff…...

FreeRTOS任务挂起以及延时部分源码分析

layout: post title: “任务状态” date: 2023-7-19 15:39:08 0800 tags: FreeRTOS 任务状态 fireRTOS代码分析 任务挂起 //把一个任务挂起 void vTaskSuspend( TaskHandle_t xTaskToSuspend ) {TCB_t *pxTCB;taskENTER_CRITICAL();//进入临界区{/* 参数是NULL的时候设置为当…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...