【Java算法】二叉树的深搜

news2024/9/20 15:03:33

  🔥个人主页: 中草药 

 🔥专栏:【算法工作坊】算法实战揭秘


一.2331.计算布尔二叉树的值

题目链接:2331.计算布尔二叉树的值

代码

public boolean evaluateTree(TreeNode root) {
        if(root.left==null){
            return root.val==0?false:true;
        }
        boolean left=evaluateTree(root.left);
        boolean right=evaluateTree(root.right);
        return root.val==2?left||right:left&right;
    }

算法原理 

是一个相对简单的递归二叉树深搜的问题,注意分析 return 的内容

这个算法基于递归树遍历布尔表达式求值的原理。具体来说:

  • 递归树遍历:从根节点开始,递归地访问每个节点,直到到达叶子节点。在回溯过程中,将叶子节点的值逐步向上层传递,并根据父节点的逻辑运算符进行组合。
  • 布尔表达式求值:通过递归的方式,最终可以将整个二叉树转换成一个布尔表达式,并计算出最终的结果。在这个过程中,每遇到一个内部节点(即值为 2 或 3 的节点),就相当于在布尔表达式中遇到了一个逻辑运算符,然后根据这个运算符对左右子树的结果进行相应的逻辑运算。

假设我们有以下二叉树:

    2
   / \
  1   3
     / \
    0   1
  • 根节点的值为 2,表示 OR 运算。
  • 左子树的根节点值为 1,直接返回 true
  • 右子树的根节点值为 3,表示 AND 运算。
    • 右子树的左子节点值为 0,直接返回 false
    • 右子树的右子节点值为 1,直接返回 true
    • 右子树的 AND 结果为 false && true,即 false
  • 最终结果为 true || false,即 true

因此,对于上面的二叉树,evaluateTree 函数会返回 true

二.求根节点到叶结点数字之和

题目链接:求根节点到叶结点数字之和

代码

public int sumNumbers(TreeNode root) {
        if(root==null){
            return -1;
        }
        return dfs(root,0);
    }

    public int dfs(TreeNode root,int preSum){
        //1.实现数字的计算
        preSum=preSum*10+root.val;
        //2.函数的出口
        if(root.left==null&&root.right==null){
            return preSum;
        }
        int ret=0;
        //3.计算所有的左支路
        if(root.left!=null){
            ret+=dfs(root.left,preSum);
        }
        //计算所有的右支路
        if(root.right!=null){
            ret+=dfs(root.right,preSum);
        }
        return ret;
    }

算法原理 

创建一个数 preNum 用于记录之前的数,可以用 preSum*10+root.val 来实现数字的计算,来实现题目要求

  1. 深度优先搜索 (DFS):这个算法使用了深度优先搜索的方法来遍历二叉树。每次递归调用时,都会沿着一个分支深入下去,直到到达叶子节点。
  2. 前缀和累积:在每次递归调用中,通过将当前节点的值乘以10并加上之前的前缀和,逐步构建从根节点到当前节点的数字。
  3. 路径和累加:当到达叶子节点时,返回当前路径形成的数字。对于非叶子节点,递归地计算其左子树和右子树的路径和,并将这些路径和累加起来。

三.814.二叉树剪枝

题目链接:814.二叉树剪枝

代码

public TreeNode pruneTree(TreeNode root) {
        if(root==null){
            return null;
        }
        root.left=pruneTree(root.left);
        root.right=pruneTree(root.right);
        if(root.left==null&&root.right==null&&root.val==0){
            return null;
        }
        return root;
    }

算法原理 

 这道题,可以看做剪枝思路的一个引入,注意函数体中 if 里面的条件实现剪枝,一步步剪枝

  1. 递归遍历:算法使用了深度优先搜索(DFS)的方式递归遍历整棵树。从根节点开始,逐步向下遍历到叶子节点,然后再回溯上来。
  2. 自底向上修剪:在递归过程中,先处理子节点,再处理父节点。这样可以在处理父节点时,已经知道子节点的状态(是否被移除)。
  3. 条件判断:对于每个节点,检查其左右子节点是否已经被移除(即 root.left == null 和 root.right == null),并且当前节点的值是否为 0。如果满足这些条件,说明当前节点是一个值为 0 的叶子节点,应该被移除。
  4. 更新引用:通过将 root.left 和 root.right 设置为递归调用的结果,来更新当前节点的子节点引用。如果子节点被移除,则相应的子节点引用会被设置为 null

详细步骤

  1. 基本情况:如果当前节点为空,直接返回 null
  2. 递归修剪:递归调用 pruneTree 处理当前节点的左子树和右子树。
  3. 检查当前节点:如果当前节点是值为 0 的叶子节点(即左右子节点都为 null 且当前节点的值为 0),则返回 null 以移除该节点。
  4. 返回结果:否则,返回当前节点,表示当前节点及其子树不需要被移除

 四.98.验证二叉搜索树

题目链接:98.验证二叉搜索树

代码

//防止出现极端数据
    long prev=Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }

        boolean left = isValidBST(root.left);

        boolean cur = false;
        if (root.val > prev) {
            prev = root.val;
            cur = true;
        }

        boolean right = isValidBST(root.right);
        return left && right && cur;
    }

算法原理

二叉搜索树的一个关键特征--中序遍历一定是升序的,正确引用全局变量可以节省函数头的设计,初始设置 cur 节点为 fasle ,符合要求才将该节点设置为 true,根据题意来设置 return 

  1. 中序遍历:这个算法利用了二叉搜索树的一个重要特性,即中序遍历(左-根-右)的结果是一个严格递增的序列。因此,通过中序遍历的方式,可以逐个检查节点的值是否满足递增的条件。
  2. 递归遍历:算法使用递归的方法进行中序遍历。先递归处理左子树,然后处理当前节点,最后递归处理右子树。
  3. 全局变量 prev:使用一个全局变量 prev 来记录上一个访问的节点的值。每次访问一个新的节点时,都检查当前节点的值是否大于 prev。如果是,则更新 prev 为当前节点的值。
  4. 有效性检查:如果在某个节点处发现当前节点的值不大于 prev,则说明该树不是有效的二叉搜索树,返回 false。否则,继续递归检查其他节点。

详细步骤

  1. 基本情况:如果当前节点为空,直接返回 true
  2. 递归检查左子树:递归调用 isValidBST 处理当前节点的左子树。
  3. 检查当前节点
    • 检查当前节点的值是否大于 prev。如果是,则更新 prev 为当前节点的值,并将 cur 设置为 true
    • 如果当前节点的值不大于 prev,则将 cur 设置为 false,表示该树不是有效的BST。
  4. 递归检查右子树:递归调用 isValidBST 处理当前节点的右子树。
  5. 返回结果:返回左子树、右子树和当前节点的检查结果的逻辑与操作。

 五.230.二叉搜索树中第k小的元素

题目链接:230.二叉搜索树中第k小的元素

代码

int count;
    int ret;
    public int kthSmallest(TreeNode root, int k) {
        count=k;
        dfs(root);
        return ret;
    }

    public void dfs(TreeNode root){
        if(root==null||count==0){
            return;
        }
        //中序遍历
        dfs(root.left);
        count--;
        if(count==0){
            ret=root.val;
        }
        //剪枝
        if(count==0){
            return;
        }
        dfs(root.right);
    }

算法原理 

由于中序遍历一定是升序的我们只需让一个 count 为k值,每遍历一次 count-- ,即可,我们还可以通过 剪枝 的方式优化代码

  1. 中序遍历:利用二叉搜索树的特性,中序遍历可以生成一个递增的序列。因此,通过中序遍历,我们可以按顺序访问所有节点。
  2. 计数器 count:使用全局变量 count 来记录还需要访问多少个节点才能到达第 k 个最小的节点。每次访问一个节点时,count 减 1。
  3. 找到目标节点:当 count 变为 0 时,说明当前节点就是第 k 个最小的节点,将其值存储在 ret 中。
  4. 剪枝优化:一旦找到第 k 个最小的节点,就不需要继续遍历剩余的节点了。通过检查 count 是否为 0,可以在找到目标节点后立即返回,从而减少不必要的计算。

详细步骤

  1. 初始化:在 kthSmallest 方法中,初始化 count 为 k
  2. 中序遍历:调用 dfs 方法开始中序遍历。
    • 递归地访问左子树。
    • 访问当前节点,将 count 减 1。
    • 如果 count 变为 0,更新 ret 为当前节点的值。
    • 如果 count 为 0,直接返回,不再访问右子树。
    • 否则,继续递归地访问右子树。
  3. 返回结果:在 kthSmallest 方法中返回 ret

六.257.二叉树的所有路径*

题目链接:257.二叉树的所有路径*

代码

 public List<String> binaryTreePaths(TreeNode root) {
        retl=new ArrayList<>();
        dfs(root,new StringBuilder());
        return retl;
    }

    public void dfs(TreeNode root,StringBuilder _path){
        //每次设置为新的,实现了回溯的时候 回到那时候的path

        //回溯
        StringBuilder path=new StringBuilder(_path);

        path.append(Integer.toString(root.val));
        if(root.left==null&&root.right==null){
            retl.add(path.toString());
            return;
        }
        path.append("->");
        //剪枝
        if(root.left!=null){
            dfs(root.left,path);
        }
        if(root.right!=null){
            dfs(root.right,path);
        }
    }

算法原理

在这道题初步运用了回溯的思想,并且用剪枝优化了函数的出口,需要仔细理解反复揣摩

  1. 深度优先搜索 (DFS):算法使用了深度优先搜索的方法来遍历整棵树。从根节点开始,逐步深入到叶子节点。
  2. 路径构建:使用 StringBuilder 来构建从根节点到当前节点的路径。每次访问一个节点时,将该节点的值添加到路径中。
  3. 回溯:通过在每次递归调用时创建一个新的 StringBuilder 对象 path,确保每次递归调用时路径都是独立的。这样在回溯时,路径可以恢复到之前的正确状态。
  4. 路径存储:当到达叶子节点时,将当前路径转换为字符串并添加到结果列表 retl 中。
  5. 剪枝优化:如果某个子树为空,则不需要继续递归处理该子树,从而减少不必要的计算。

详细步骤

  1. 初始化:在 binaryTreePaths 方法中,初始化 retl 为一个新的 ArrayList
  2. 递归遍历:调用 dfs 方法开始深度优先搜索。
    • 创建一个新的 StringBuilder 对象 path,并将其内容初始化为 _path 的内容。
    • 将当前节点的值添加到 path 中。
    • 如果当前节点是叶子节点,将 path 转换为字符串并添加到 retl 中。
    • 否则,在路径末尾添加 "->"
    • 递归地处理左子树和右子树,分别传入当前路径 path
  3. 返回结果:在 binaryTreePaths 方法中返回 retl

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

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

相关文章

VSCode值得推荐的插件(持续更新中)

VSCode值得推荐的插件&#xff08;持续更新中&#xff09; 说明1.Peacock 说明 主要记录VSCode开发过程中插件 1.Peacock 允许开发者为 Visual Studio Code 的工作区界面&#xff08;如侧边栏、底栏和标题栏&#xff09;自定义颜色&#xff0c;以区分不同的项目或编码环境。…

【machine learning-七-线性回归之成本函数】

监督学习之cost function 成本函数权重、偏置如何实现拟合数据成本函数是如何寻找出来w和b&#xff0c;使成本函数值最小化&#xff1f; 在线性回归中&#xff0c;我们说到评估模型训练中好坏的一个方法&#xff0c;是用成本函数来衡量&#xff0c;下面来详细介绍一下 成本函数…

需求3:照猫画虎

说起写需求&#xff0c;其实对于我这种小白而言&#xff0c;接到一个需求&#xff0c;最好的方式就是照猫画虎。 因为我从0到1写&#xff0c;以我现在这种水平&#xff0c;根本就不可能完成。所以照猫画虎&#xff0c;模仿着来写是最好的提升方法。 之前在聊天的时候&#xf…

记录|如何对批量型的pictureBox组件进行批量Image设置

目录 前言一、问题表述二、批量化处理更新时间 前言 参考文章&#xff1a; 一、问题表述 问题就是上图所示&#xff0c;这些的命名风格统一&#xff0c;只是最后的数字是不同的。所以存在可以批量化进行处理的可能性。 二、批量化处理 private void SetPictureBoxImages(){for…

Flat File端口更新:如何实现嵌套结构

Flat File端口可以实现平面文件和XML文件的互相转换&#xff0c;本文主要介绍在知行之桥EDI系统8971及更高版本中&#xff0c;Flat File端口如何支持类似EDI嵌套结构的转换。 Flatfile端口如何自定义嵌套结构 下载示例工作流以及示例文件 打开知行之桥EDI系统&#xff0c;创建…

OpenCV特征检测(1)检测图像中的线段的类LineSegmentDe()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 检测图像中线段的类.。 遵循在 285中描述的算法。 函数原型1 绘制两组线&#xff0c;一组用蓝色&#xff0c;一组用红色&#xff0c;并计算非重…

[云服务器12] 搭建eaglercraft网页MC

众所周知&#xff0c;MC是一个炒鸡好玩的游戏&#xff01; 但是&#xff0c;Mojang开发出来是经过Java JAR打包过的的.jar文件&#xff0c;这就不得不依赖HMCL PCL BakaXL等启动器来启动了…… 所以今天&#xff0c;我们将使用开源的eaglercraft来搭建一个在线版MC&#xff0…

鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别

一、介绍 鸟类识别系统。本系统采用Python作为主要开发语言&#xff0c;通过使用加利福利亚大学开源的200种鸟类图像作为数据集。使用TensorFlow搭建ResNet50卷积神经网络算法模型&#xff0c;然后进行模型的迭代训练&#xff0c;得到一个识别精度较高的模型&#xff0c;然后在…

【VUE3.0】动手做一套像素风的前端UI组件库---Button

目录 引言做之前先仔细看看UI设计稿解读一下都有哪些元素&#xff1a;素材补充 代码编写1. 按钮四周边框2. 默认状态下按钮颜色立体效果3. 鼠标移入聚焦4. 模拟鼠标点击效果 组件封装1. 按类型设置颜色2. 设置按钮禁用状态3. 处理一个bug4. 看下整体组件效果5. 组件完整代码6. …

数字自然资源领域的实现路径

在数字化浪潮的推动下&#xff0c;自然资源的管理与利用正经历着前所未有的变革。本文将从测绘地理信息与遥感专业的角度&#xff0c;深度分析数字自然资源领域的实现路径。 1. 基础数据的数字化 数字自然资源的构建&#xff0c;首先需要实现基础数据的数字化。这包括地形地貌…

db2恢复数据库

db2licm -l检查下license IBM Support: Fix Central - Please wait, Select fixes db2 force application all db2ckbkp -H JYC.0.DB2.NODE0000.CATN0000.20240603223001.001 db2 "restore db jyc logtarget x:\db2\log" db2 "rollforward db jyc to end of log…

音频北斗定位系统有什么用?

在当今科技飞速发展的时代&#xff0c;定位技术已经成为我们日常生活和各行各业不可或缺的一部分。其中&#xff0c;音频北斗定位系统作为一种新兴的定位技术&#xff0c;正逐渐展现出其独特的优势和应用价值。那么&#xff0c;到底音频北斗定位系统有什么用呢?我们一起来了解…

住宅代理IP如何提高 IP声誉?

你有没有遇到过类似的问题&#xff1f;发送的邮件被标记为垃圾邮件并被屏蔽、访问某些网站被拒绝、广告效果不理想&#xff0c;甚至网上交易无缘无故被拒绝&#xff1f;这到底是什么原因造成的&#xff1f;其实&#xff0c;这些问题可能都和 IP 信誉息息相关。 如果你的 IP 地址…

一文读懂HPA弹性扩展以及实践攻略

一文读懂HPA弹性扩展以及实践攻略 目录 1 概念&#xff1a; 1.1 什么是弹性扩展1.2 HPA 的工作原理1.3 通过监控指标来调整副本数 1.3.1 计算公式说明1.3.2 平均值计算1.3.3 未就绪 Pod 和丢失的指标处理1.3.4 多指标支持1.3.5 缩减副本的平滑策略 1.4 HPA的优缺点 2 实践攻略…

微服务保护学习笔记(五)Sentinel授权规则、获取origin、自定义异常结果、规则持久化

文章目录 前言4 授权规则4.1 基本原理4.2 获取origin4.3 配置授权规则 5 自定义异常结果6 规则持久化 前言 微服务保护学习笔记(一)雪崩问题及解决方案、Sentinel介绍与安装 微服务保护学习笔记(二)簇点链路、流控操作、流控模式(关联、链路) 微服务保护学习笔记(三)流控效果(…

C语言 14 结构体 联合体 枚举

之前认识过很多种数据类型&#xff0c;包括整数、小数、字符、数组等&#xff0c;通过使用对应的数据类型&#xff0c;就可以很轻松地将数据进行保存了&#xff0c;但是有些时候&#xff0c;这种简单类型很难去表示一些复杂结构。 结构体 比如现在要保存 100 个学生的信息&am…

本地部署一个轻量化智能聊天服务Vocechat并实现异地远程交互

文章目录 前言1. 拉取Vocechat2. 运行Vocechat3. 本地局域网访问4. 群晖安装Cpolar5. 配置公网地址6. 公网访问小结 7. 固定公网地址 前言 本文主要介绍如何在本地群晖NAS搭建一个自己的聊天服务Vocechat&#xff0c;并结合内网穿透工具实现使用任意浏览器远程访问进行智能聊天…

我的AI工具箱Tauri版-VideoReapeat视频解说复述克隆

本教程基于自研的AI工具箱Tauri版进行VideoReapeat视频解说复述克隆。 VideoReapeat视频解说复述克隆 是自研的AI工具箱Tauri版中的一款专用模块&#xff0c;旨在通过AI技术对视频解说内容进行复述和克隆。该工具可自动洗稿并重新生成视频解说&#xff0c;通过简单配置即可对大…

协同编程的艺术:SIDE 让团队协作更上一层楼

一、协同编程的现状 在当前软件开发中&#xff0c;团队协作面临着诸多挑战。沟通不畅常常导致项目进度延迟&#xff0c;版本控制复杂使得代码合并困难重重。传统 IDE 在协同工作方面存在明显的局限性&#xff0c;缺乏实时协作功能&#xff0c;团队成员之间的沟通工具也不够完善…

如何上传tauri项目到csdn gitcode

如何上传tauri项目到csdn gitcode 首先保证项目目录有.gitignore&#xff0c;避免不必要的文件上传分享。 gitignore文件 # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log*node_modules dist dist-ssr *.local# Editor …