【代码随想录刷题】Day18 二叉树05

在这里插入图片描述

文章目录

  • 1.【513】找树左下角的值
    • 1.1题目描述
    • 1.2 解题思路
      • 1.2.1 迭代法思路
      • 1.2.2 递归法思路
    • 1.3 java代码实现
      • 1.3.1 迭代法java代码实现
      • 1.3.2 递归法java代码实现
  • 2. 【112】路径总和
    • 2.1题目描述
    • 2.2 解题思路
    • 2.3 java代码实现
  • 3.【106】从中序与后序遍历序列构造二叉树
    • 3.1题目描述
    • 3.2 解题思路
    • 3.3 java代码实现

【513】找树左下角的值
【112】路径总和
【106】从中序与后序遍历序列构造二叉树

1.【513】找树左下角的值

1.1题目描述

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

假设二叉树中至少有一个节点。
在这里插入图片描述
提示:

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

1.2 解题思路

1.2.1 迭代法思路

本题要找出树的最后一行的最左边的值,使用层序遍历是非常简单的,只需要记录最后一行第一个节点的数值就可以了。

1.2.2 递归法思路

题目:在树的最后一行找到最左边的值

首先要是最后一行,然后是最左边的值。

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

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

递归三部曲

    1. 确定递归函数的参数和返回值

参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。 这里就不需要返回值了,所以递归函数的返回类型为void。

本题还需要类里的两个全局变量,maxDepth用来记录最大深度,result记录最大深度最左节点的数值。

	int result;// 全局变量 记录最大深度
    int maxDepth=-1;// 全局变量 最大深度最左节点的数值
    public void traversal(TreeNode root,int depth)
    1. 确定终止条件

当遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。

		if (root.left==null && root.right==null){
            if (depth>maxDepth){
                maxDepth=depth;// 更新最大深度
                result=root.val;// 最大深度最左面的数值
            }
            return;
        }
    1. 确定单层递归的逻辑

在找最大深度的时候,递归的过程中依然要使用回溯

		if (root.left!=null){//左
        	depth++;
            traversal(root.left,depth);//回溯
            depth--;
        }
        if (root.right!=null){//右
        	depth++;
            traversal(root.right,depth);//回溯
            depth--;
        }
        return;

1.3 java代码实现

1.3.1 迭代法java代码实现

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        //迭代法  层次遍历
        Queue<TreeNode> que=new LinkedList<>();
        que.offer(root);

        int res=0;
        while (!que.isEmpty()){
            int len=que.size();
            for (int i = 0; i < len; i++) {
                TreeNode tempNode=que.poll();
                // 记录最后一行第一个元素
                if (i==0){
                    res=tempNode.val;
                }
                if (tempNode.left!=null){
                    que.offer(tempNode.left);
                }
                if (tempNode.right!=null){
                    que.offer(tempNode.right);
                }
            }
        }
        return res;

    }
}

1.3.2 递归法java代码实现

class Solution {
    int result;// 全局变量 记录最大深度
    int maxDepth=-1;// 全局变量 最大深度最左节点的数值
    public int findBottomLeftValue(TreeNode root) {
        //递归
        traversal(root,0);
        return result;
    }
    public 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!=null){//左
        	depth++;
            traversal(root.left,depth);//回溯
            depth--;
        }
        if (root.right!=null){//右
        	depth++;
            traversal(root.right,depth);//回溯
            depth--;
        }
        return;
    }
}

递归函数简写:

public 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!=null){//左
            traversal(root.left,depth+1);// 隐藏着回溯
        }
        if (root.right!=null){//右
            traversal(root.right,depth+1);// 隐藏着回溯
        }
        return;
    }

2. 【112】路径总和

2.1题目描述

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

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

在这里插入图片描述
提示:

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

2.2 解题思路

本题可以采用深度遍历的方式来遍历(本题前中后序都可以,无所谓,因为根节点也没有处理逻辑)。,递归法

请添加图片描述

2.3 java代码实现

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
         if (root==null){
            return false;
        }

        targetSum -= root.val;
        //叶子结点
        if (root.left==null && root.right==null){
            return targetSum==0;
        }
        if (root.left!=null){
            boolean left=hasPathSum(root.left,targetSum);
            //已经找到
            if (left){
                return true;
            }
        }
        if (root.right!=null){
            boolean right=hasPathSum(root.right,targetSum);
            //已经找到
            if (right){
                return true;
            }
        }
        return false;
    }
}

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

3.1题目描述

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
在这里插入图片描述
提示:

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

3.2 解题思路

中序遍历与后序遍历构造二叉树的理论知识

以 后续数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后续数组。一层一层的切下去,每次后续数组的最后一个元素就是节点元素。

流程如下:

在这里插入图片描述

代码该怎样写呢?提到一层一层切割,就应该想到了递归

    1. 如果数组大小为0的话,说明是空节点了
    1. 如果不为空,那么取后序数组的最后一个元素作为节点元素
    1. 找到后序数组最后一个元素在中序数组中的位置,作为切割点
    1. 切割中序数组,切成中序左数组和中序右数组(顺序一定不能弄反了,一定要先切中序数组)
    1. 切割后序数组,切成后序左数组和后序右数组
    1. 递归处理左区间和右区间

3.3 java代码实现

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
		if (postorder.length==0 || inorder.length==0){
            return null;
        }
        return buildHelper(inorder,0,inorder.length,postorder,0, postorder.length);
    }
    public TreeNode buildHelper(int[] inorder,int inorderBegin,int inorderEnd,int[] postorder,int postBegin,int postEnd){
        if (postBegin==postEnd){
            return null;
        }
        //根节点
        int rootVal=postorder[postEnd-1];

        TreeNode root=new TreeNode(rootVal);

        //切割点
        int middleIndex;
        for (middleIndex=inorderBegin;middleIndex<inorderEnd;middleIndex++){
            if (inorder[middleIndex]==rootVal){
                break;
            }
        }

        //切割中序数组
        //左中序数组,左闭右开[leftInorderBegin,leftInoderEnd)
        int leftInorderBegin=inorderBegin;
        int leftInoderEnd=middleIndex;
        //右中序数组,左闭右开[rightInorderBegin,leftInoderEnd)
        int rightInorderBegin=middleIndex+1;
        int rightInoderEnd=inorderEnd;

        //切割后序数组
        //左后序数组,左闭右开[leftPostorderBegin,leftPostoderEnd)
        int leftPostorderBegin=postBegin;
                //终止位置是 需要加上 中序区间的大小size
        int leftPostoderEnd=postBegin+(middleIndex-inorderBegin);


        //右后序数组,左闭右开[rightPostorderBegin,leftPostoderEnd)
        int rightPostorderBegin=leftPostoderEnd;
        int rightPostoderEnd=postEnd-1;//排除最后一个元素,已经作为节点了

        root.left=buildHelper(inorder,leftInorderBegin,leftInoderEnd,postorder,leftPostorderBegin,leftPostoderEnd);
        root.right=buildHelper(inorder,rightInorderBegin,rightInoderEnd,postorder,leftPostorderBegin,rightPostoderEnd);

        return root;

    }
}
class Solution {
    Map<Integer,Integer> map;//方便根据数值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {

        map=new HashMap<>();
        // 用map保存中序序列的数值对应位置
        for (int i=0;i<inorder.length;i++){
            map.put(inorder[i],i );
        }

        return findNode(inorder,0,inorder.length,postorder,0,postorder.length);
    }

    public TreeNode findNode(int[] inorder,int inorderBegin,int inorderEnd,int[] postorder,int postBegin,int postEnd){
        //参数里的范围都是左闭右开
        if (inorderBegin>=inorderEnd || postBegin>=postEnd){
            return null;
        }

        // 找到后序遍历的最后一个元素在中序遍历中的位置
        int rootIndex=map.get(postorder[postEnd-1]);
        TreeNode root=new TreeNode(inorder[rootIndex]);//构造节点

        //保存中序左子树个数,用来确定后序数列的个数
        int lenOfleft=rootIndex-inorderBegin;

        root.left=findNode(inorder,inorderBegin,rootIndex,postorder,postBegin,postBegin+lenOfleft);
        root.right=findNode(inorder,rootIndex+1,inorderEnd,postorder,postBegin+lenOfleft,postEnd-1);

        return root;
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6.前端--CSS-基础选择器【2023.11.26】

1.CSS基本选择器 标签选择器&#xff1a; 标签选择器&#xff08;元素选择器&#xff09;是指用 HTML 标签名称作为选择器&#xff0c;按标签名称分类&#xff0c;为页面中某一类标签指定统一的 CSS 样式。标签选择器可以把某一类标签全部选择出来&#xff0c;比如所有的 <…

js原理网页内容防复制-原理、实现及破解

大家好&#xff0c;这一集我们来看一下如何通过js代码实现网页内容防复制&#xff0c;并且使用代码复现效果&#xff0c;同时如何破解这种防复制。 视频教程链接&#xff1a;https://www.bilibili.com/video/BV1zM41197y7/ 代码删掉即可&#xff0c;删不掉关闭设置 您可以使用…

基于STC12C5A60S2系列1T 8051单片按页写IIC总线器件24C02并显示在液晶显示器LCD1602上应用

基于STC12C5A60S2系列1T 8051单片机按页写IIC总线器件24C02并显示在液晶显示器LCD1602上应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍…

Android设计模式--桥接模式

闻正言&#xff0c;行正道&#xff0c;左右前后皆正人 一&#xff0c;定义 将抽象部分与实现部分分离&#xff0c;使它们都可以独立地进行变化 二&#xff0c;使用场景 从模式的定义中&#xff0c;我们大致可以了解到&#xff0c;这里的桥接的作用其实就是连接抽象部分与实现…

DDD落地:从阿里单据系统,看DDD在大厂如何落地?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#x…

【libGDX】Mesh立方体贴图(6张图)

1 前言 本文通过一个立方体贴图的例子&#xff0c;讲解三维纹理贴图的应用&#xff0c;案例中使用 6 张不同的图片给立方体贴图&#xff0c;图片如下。 读者如果对 libGDX 不太熟悉&#xff0c;请回顾以下内容。 使用Mesh绘制三角形使用Mesh绘制矩形使用Mesh绘制圆形使用Mesh绘…

原生DOM事件、react16、17和Vue合成事件

目录 原生DOM事件 注册/绑定事件 按DOM事件级别分类&#xff0c;越小越高 DOM0&#xff1a;onclick传统注册&#xff1a; 唯一&#xff08;同元素的(不)同事件会覆盖&#xff09; 没有捕获和冒泡的&#xff0c;只有简单的事件绑定 DOM2&#xff1a;addEventListener监听…

Mybatis反射核心类Reflector

Reflector类负责对一个类进行反射解析&#xff0c;并将解析后的结果在属性中存储起来。 一个类反射解析后都有哪些属性呢&#xff1f;我们可以通过Reflector类定义的属性来查看 public class Reflector {// 要被反射解析的类private final Class<?> type;// 可读属性列…

【聚类 | K-means】原理及推导流程(附模板代码,库手撕实现)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

shell脚本 ( 函数 数组 冒泡排序)

目录 什么是函数 使用函数的方法 格式 注意事项 函数的使用 函数可以直接使用 函数变量的作用范围 函数返回值 查看函数 删除函数 函数的传递参数 使用函数文件 ​编辑 拓展递归函数 例&#xff1a;求5的阶乘 什么是数组 使用数组的方法 1.先声明 2.定义数组 3…

MQTT客户端MQTT.fx 1.7.1下载、安装和界面介绍

MQTT.fx是一款基于Eclipse Paho&#xff0c;使用Java语言编写的MQTT客户端工具。支持通过Topic订阅和发布消息&#xff0c;用来前期和物理云平台调试非常方便。 1.下载 1.1.访问官方下载地址下载&#xff0c;但是下载不到1.7.1版本 1.2.在连接网页末尾点击立即下载&#xff0c;…

思维模型 古烈治效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。见异思迁。 1 古烈治效应的应用 1.1 古烈治效应之心理学研究 在一项研究中&#xff0c;研究者让男性和女性参与者分别观看一系列异性的照片&#xff0c;并评估他们的吸引力。在观看完所有…

(三) Windows 下 Sublime Text 3 配置Python环境和Anaconda代码提示

一&#xff1a;新建一个 Python3.7 编译环境。 1 Tools--Build System--New Build System... 修改前&#xff1a; 修改后&#xff1a; 内容&#xff1a; {"cmd":["C:\\Python\\Python37-32\\python.exe","-u","$file"],"file_r…

Java基于springboot+vue开发服装商城小程序

演示视频&#xff1a; 小程序 https://www.bilibili.com/video/BV1rM411o7m4/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 管理员 https://www.bilibili.com/video/BV1fc411D7V3/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae…

CV计算机视觉每日开源代码Paper with code速览-2023.11.21

点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构&#xff1a;Transformer】Multi-entity Video Transformers for Fine-Grained Video Representation Learning 论文地址&…

WordPress最廉价优化整站的加载速度

为什么说一个站不优化就等于一个人做整个团队的事务导致项目进展慢&#xff0c;网站也是如此 图片、静态文件、php分离加速&#xff0c;加载速度并不是很快但是很协调比单个网站加载速度快许多 一、图片单域名加载设置上传文件路径和域名 以下代码添加在主题目录&#xff1a;fu…

大数据基础 HDFS客户端操作

一、Maven概述 Maven是一个专门用于管理和构建Java项目的工具。我们之所以要使用Maven&#xff0c;是因为Maven可以为我们提供一套标准化的项目结构、一套标准化的构建流程和一套方便的依赖管理机制&#xff0c;这些功能可以使得我们的项目结构更加清晰&#xff0c;导入jar包的…

Effective Modern C++(1.顶层const与底层const)

1.顶层const与底层const的定义 const修饰的变量不可以改变&#xff0c;那么他就是顶层const&#xff0c;如&#xff1a; const int a 10; 那么&#xff0c;对于 const int *const p new int(10); 第二个const就是顶层const&#xff0c;因为他修饰的是p&#xff1b;第一个…

容器技术——Cgroup

目录 容器技术容器技术概述要区分好共享与隔离的概念容器技术的三大核心容器对比虚拟机 namespaceUnionFs容器操作系统的来源操作系统的来源完整操作系统的镜像docker image是什么&#xff1f;如何构成的 如何为容器安装操作系统UnionFS&#xff08;联合文件系统&#xff09;的…

23.11.26日总结

图片与文字顶部对齐&#xff1a; <div class"addDishImgBox"><span class"addDishImgZi">商品图片&#xff1a;</span><img :src"myStorePhoto" class"addDishImg"> </div> .addDishImgBox{display: f…