【递归、搜索和回溯算法】专题二 :二叉树中的深搜

news2025/3/14 11:50:32

二叉树中的深搜 


深度优先遍历(DFS):一种沿着树或图的深度遍历节点的算法,尽可能深地搜索树或图的分支,如果一条路径上的所有结点都被遍历完毕,就会回溯到上一层,继续找一条路遍历。

在二叉树中,常见的深度优先遍历:前序遍历、中序遍历、后序遍历,树的定义本身就是递归的定义。

搜索题型 

1.计算布尔二叉树

2331. 计算布尔二叉树的值 - 力扣(LeetCode)

 题目说了只有叶子结点本身才是布尔类型的值,其他的节点都需要进行运算后才是布尔类型的值。

面对这道题,首先我们就需要知道根结点左右两边的布尔值,但是要计算左右两边的又需要它们左右两边的布尔值,就需要用到递归算法来计算左右两边的布尔值。

     递归三步      

  • 函数头

boolean evaluateTree(TreeNode root)

直接传入一个节点的参数就可以;

  • 函数体

先访问左子树,再访问右子树,最后返回当前的节点是2还是3后计算后的布尔值(是2将左右子树通过逻辑或计算,是3就通过逻辑与计算)。【:逻辑或(|):如果左右子树全为假该节点就为假,如果左右子树中有一个为真那就该节点为真。逻辑与(&):如果左右子树全为真该节点就为真,如果左右子树中有一个为假那就该节点为假】

  • 递归出口

当遇到叶子结点时,如果该节点的值为0就返回false,相反不是0就返回true;

    编写代码    

    public boolean evaluateTree(TreeNode root) {
       if(root.left == null && root.right == 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;
    }

2.求根节点到叶节点数字之和

 129. 求根节点到叶节点数字之和 - 力扣(LeetCode)

首先我们把dfs这个方法看作一个黑盒,相信他一定可以得到我们想要的结果。每走到一个节点我们都需要前一个结点的值,这就是关键,我们要知道递归的子问题在做什么。

将上面例子进行分析,当我们到3这个节点时我们要拿到13,所以返回类型需要一个int类型来接收,然后传给访问左节点再访问右节点。每一个交界点都需要将后面所有的结果返回交界点,让交界点负责再往回送最后到头节点,所以在这过程中需要两个变量一个用来记录当前节点之和,一个用来记录左右节点返回的值之和,当左右节点为空时就返回记录当前节点的值,如果不为空那就返回记录左右节点的返回的值之和。

     递归三步      

  • 函数头

int dfs(TreeNode root, int presum)

  • 函数体

首先需要更新当前节点之和presum = 10*presum + root.val,将更新后的节点之和传个左右子树(要判断是否有左右子树),这里还需要用到回溯,如果该节点的左右子树已经求完还需要往回找到交界节点,继续左右子树求和返回;

  • 递归出口

如果是叶子结点那就直接返回当前节点之和presum;

    编写代码    

    public int sumNumbers(TreeNode root) {
        return dfs(root, 0);
    }
    public int dfs(TreeNode root, int prenum){
        prenum = prenum*10+root.val;
        if (root.left == null && root.right == null){
            return prenum;
        }
        int ret = 0;
        if (root.left != null){
            ret += dfs(root.left, prenum);
        }
        if (root.right != null){
            ret += dfs(root.right, prenum);
        }
        return ret;
    }

3.二叉树的剪枝

 814. 二叉树剪枝 - 力扣(LeetCode)

如果这颗子树的所有结点的值全为0那就可以将这个子树剪掉。所以并不是将所有的0都剪掉。 

要想找到全为0的子树,那就需要知道左右子树的所有信息,如果我们遍历到叶子结点时该节点的值为0那我们就剪去这个叶子结点返回上一层,那怎么剪呢?如果是叶子结点那就返回null。所以返回值需要进行接收,这样函数头就设计好了。

     递归三步      

  • 函数头

TreeNode pruneTree(TreeNode root),把该结点所在的左右子树中,所有包含0的子树移除移完后;

  • 函数体

先访问左子树,再访问右子树,如果叶子结点的值为0就返回空指针,不是空返回当前节点。

  • 递归出口

如果该节点为空就返回空指针

    编写代码    

    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;
        }else{
            return root;
        }
    }

4.验证二叉搜索树

 98. 验证二叉搜索树 - 力扣(LeetCode)

二叉搜索树:左子树的值要小于根节点的值,右子树的值要大于根结点的值,一棵树中每一棵子树都满足该定义的树就是二叉搜索树;

我们要借助中序遍历是一个有序的这个结论,就可以通过全局变量来比较每一个结点,每比较完一次就将该节点的值给全局变量,这样只要一出现不合理的就返回false。但是如果我们再中途中发现了false,我们就不再需要继续往后进行遍历了,直接剪枝。只有当左右子树以及根结点都满足true那就返回true。【:设置全局变量时我们需要一个最小值,题目范围是int的最小最大,但是如果二叉树中存在最小值时,那就不能比较了,所以我们设置全局变量时用long的最小值】

     递归三步      

  • 函数头

boolean isValidBST(TreeNode root),需要一个布尔返回值辨别是否符合定义,还需要一个当前节点;

  • 函数体

首先先判断左子树,如果存在false直接剪枝,再判断当前结点,如果存在false直接剪枝,最后盘算右子树,最后返回左根右子树的逻辑与值;

  • 递归出口

如果当前节点为空时返回true

    编写代码    

    long pre = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null){
            return true;
        }
        boolean left = isValidBST(root.left);
        if (left == false){
            return false;
        }
        boolean cur = false;
        if (pre < root.val){
            cur = true;
        pre = root.val;
        }
        if (cur == false){
            return false;
        }
        boolean right = isValidBST(root.right);
        return left && cur && right;
    }

5.二叉树中第k小的元素

230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

只要设计有序的二叉树,一般都需要用到中序遍历,再结合上一题中的全局变量那么这道题就跟简单了,做法与上一题的验证二叉搜索树相像。

我们可以设置全局变量来计数,在通过全局变量来记录题目要求的第k小的元素,先遍历左子树,直到到达最小值,开始计数如果count值等于题目已知的k,那么用ret记录下来并且count加1(这里count为什么要加1?因为如果不加那么下一次再比较时还是相等那就不符合题意),返回ret即可但是如果不是那么count也要加1,然后再遍历右子树,最后返回记录值ret;

     递归三步      

  • 函数头

int kthSmallest(TreeNode root, int k),需要返回一个第k小值,还需要一直知道k的值,以及当前节点

  • 函数体

同样先左子树,当前节点判断,再右子树(中序遍历)

  • 递归出口

如果当前节点为空,那就返回0;

    编写代码    

    //全局变量
    public int count = 1;
    public int ret = 0;

    public int kthSmallest(TreeNode root, int k) {
        if (root == null){
            return 0;
        }
        kthSmallest(root.left, k);
        if (count == k) {
            ret = root.val;
            count++;
            return ret;
        } else {
            count++;
        }
        kthSmallest(root.right, k);
        return ret;
    }

6.二叉树所有路径 

257. 二叉树的所有路径 - 力扣(LeetCode)

我们需要一个全局变量来记录链表,每完成一条路经就将这条路径转成字符串添加到链表中。 

开始时我们会从根节点开始遍历记录所有分支,直到叶子结点为结束这就是一条完整的路径,我们可以用字符串来接收。每遍历一个新的结点我们都先把原先结点的记录都保存新的字符串中,然后再将该节点放进新字符串中(对于这种时不时添加字符,如果用String那就不好添加,String很难改变原本结构,所以我们可以用StringBuffer来进行随意添加操作),先记录在访问后序的结点。如果当前节点已经是叶子节点了那就将新建的字符串添加到链表中再结束这条路经,但如果不是那就添加一个箭头再进行左子树和右子树的操作。

     递归三步      

  • 函数头

void dfs(TreeNode root, StringBuffer _path),需要一个字符串来记录路径。

  • 函数体

创建一个新的StringBuffer记录原先字符串再添加当前节点值,如果是叶子节点结束,不是那就继续左子树右子树递归

  • 递归出口

当遇到叶子结点那就添加结束返回;

    编写代码    

    List<String> ret;

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

    public void dfs(TreeNode root, StringBuffer _path) {
        StringBuffer path = new StringBuffer(_path);
        path.append(Integer.toString(root.val));
        if (root.left == null && root.right == null) {
            ret.add(path.toString());
            return ;
        } else {
            path.append("->");
            if (root.left != null) {
                dfs(root.left, path);
            }
            if (root.right != null) {
                dfs(root.right, path);
            }
        }
    }

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

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

相关文章

【vue3学习笔记】(第150-151节)computed计算属性;watch监视ref定义的数据

尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 本篇内容对应课程第150-151节 课程 P150节 《computed计算属性》笔记 写一个简单的 姓、名输入框效果&#xff1a; 用vue2的形式定义一个计算属性 fullName&#xff1a; 测试页面展示无问题&#xff1a; 但是&#xff0c;在vue…

MySQL 8 设置允许远程连接(Windows环境)

&#x1f31f; MySQL 8 设置允许远程连接&#xff08;Windows环境&#xff09; 在开发和部署应用时&#xff0c;经常需要从远程主机连接到MySQL数据库。默认情况下&#xff0c;MySQL仅允许本地连接&#xff0c;因此需要进行一些配置才能允许远程访问。今天&#xff0c;我将详细…

我又又又又又又更新了~~纯手工编写C++画图,有注释~~~

再再再次感谢Ttcofee提的问题 本次更新内容&#xff1a; 鼠标图案&#xff08;切换&#xff09;&#xff0c;版本号获取&#xff0c;输入框复制剪切板 提前申明&#xff1a;如果运行不了&#xff0c;请到主页查看RedpandaDevc下载&#xff0c;若还是不行就卸了重装。 版本号&…

全面解析:将采购入库单数据集成到MySQL的技术实施

旺店通旗舰版-采购入库单集成到MySQL的技术案例分享 在数据驱动的业务环境中&#xff0c;如何高效、准确地实现系统间的数据对接是企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例&#xff1a;将旺店通旗舰奇门平台上的采购入库单数据集成到MySQL数据库中&#x…

12. Pandas :使用pandas读Excel文件的常用方法

一 read_excel 函数 其他参数根据实际需要进行查找。 1.接受一个工作表 在 11 案例用到的 Excel 工作簿中&#xff0c;数据是从第一张工作表的 A1 单元格开始的。但在实际场景中&#xff0c; Excel 文件可能并没有这么规整。所以 panda 提供了一些参数来优化读取过程。 比如 s…

记录致远OA服务器硬盘升级过程

前言 日常使用中OA系统突然卡死&#xff0c;刷新访问进不去系统&#xff0c;ping服务器地址正常&#xff0c;立马登录服务器检查&#xff0c;一看磁盘爆了。 我大脑直接萎缩了&#xff0c;谁家OA系统配400G的空间啊&#xff0c;过我手的服务器没有50也是30台&#xff0c;还是…

Java网络多线程

网络相关概念: 关于访问: IP端口 因为一个主机上可能有多个服务, 一个服务监听一个端口,当你访问的时候主机通过端口号就能知道要和哪个端口发生通讯.因此一个主机上不能有两个及以上的服务监听同一个端口. 协议简单来说就是数据的组织形式 好像是两个人交流一样,要保证自己说…

VScode 运行LVGL

下载vscode解压 环境安装 安装mingw64&#xff0c;gcc 版本必须8.3以上 安装cmak 系统环境变量Path中添加&#xff08;以实际安装目录为准&#xff09; C:\Program Files\mingw64\bin C:\Program Files\CMake\bin 将GUI-Guider生成的代码目录拷贝一份放到vscode项目目录…

React Next项目中导入Echart世界航线图 并配置中文

公司业务要求做世界航线图&#xff0c;跑了三个ai未果&#xff0c;主要是引入world.json失败&#xff0c;echart包中并不携带该文件&#xff0c;源码的world.json文件页面404找不到。需要自己寻找。这是整个问题卡壳的关键点&#xff0c;特此贴出资源网址。 目录 一、安装 二…

QT与网页显示数据公式的方法

一.网页中显示数学公式通常有三种主要方法 1.图片方式 原理&#xff1a;将公式转换为图片&#xff08;如 PNG、SVG&#xff09;&#xff0c;通过 <img> 标签嵌入网页。 实现步骤&#xff1a; 使用工具&#xff08;如 LaTeX dvipng、在线生成工具&#xff09;将公式渲…

深入解析APP订阅页的运作机制(订阅页如何运作)

在当今数字经济的背景下&#xff0c;订阅模式已成为许多企业获取稳定收入的重要方式。无论是软件、视频流媒体还是电子商务&#xff0c;订阅服务都能为用户提供持续的价值体验。然而&#xff0c;如何有效地设计和运作一个订阅页&#xff0c;是决定用户是否愿意订阅的关键因素。…

Golang倒腾一款简配的具有请求排队功能的并发受限服务器

golang官方指南[1]给了一些代码片段&#xff0c;层层递进演示了信道的能力: 1>. 信号量2>. 限流能力 var sem make(chan int, MaxOutstanding) func Serve(queue chan *Request) {for req : range queue {req: reqsem <- 1 go func() { // 只会开启MaxOutstandin…

【运维】服务器系统从centos7重装为ubuntu22.04

目录 一、硬盘准备二、系统安装三、安装基本系统组件四、挂载机械硬盘五、问题解决 一、硬盘准备 【注意&#xff1a;这一步会把硬盘的数据清空&#xff0c;所以需要找一个空的U盘或者把U盘数据备份】 ubuntu22.04下载 需要先安装 bittorrent 下载完之后会打开一个网页 然后…

创新技术引领软件供应链安全,助力数字中国建设

编者按 随着数字化转型的加速&#xff0c;针对软件供应链的攻击事件呈快速增长态势&#xff0c;目前已成为网络空间安全的焦点。如何将安全嵌入到软件开发到运营的全流程&#xff0c;实现防护技术的自动化、一体化、智能化&#xff0c;成为技术领域追逐的热点。 悬镜安全作为…

【设计模式】建造者模式——工厂模式

三、建造者模式——工厂模式 3.1 工厂模式 创建一个类对象的传统方式是使用关键字new, 因为用new 创建的类对象是一个堆对象&#xff0c;可以实现多态。工厂模式通过把创建对象的代码包装起来&#xff0c;实现创建对象的代码与具体 的业务逻辑代码相隔离的目的(将对象的创建和…

蓝桥备赛(18)- 红黑树和 set 与 map(上)

对于二叉搜索树 &#xff0c; 平衡二叉树 &#xff0c; 以及红黑树 &#xff0c; 目前只需要了解背后的原理 &#xff0c; 不做代码实现的要求 &#xff0c; 重要的就是了解各种操作的时间复杂度即可 &#xff0c; 为set 与 map 做铺垫 一、二叉搜索树 1.1 基本概念 相较与于堆…

obeaver 连接oracle 库 模式乱码

下载orai18n-12.1.0.2.0.jar 库--添加文件--把提前下载好的jar 随便放在一个文件夹下--添加文件选中&#xff0c;然后点击找到类&#xff0c; 选择类&#xff0c;确定即可正常 下载地址&#xff1a;https://download.csdn.net/download/weixin_42845364/88368302

ChatGPT 使用教程:深度探索AI常用功能技巧

文章目录 前言一、ChatGPT介绍1.1 人工智能与自然语言处理的发展1.2 ChatGPT 的诞生与意义 二、ChatGPT 基础入门2.1 注册与登录2.2 对话界面介绍2.3 基本提问方式 三、常用功能详解3.1 文本生成3.2 问题回答3.3 语言翻译3.4 代码生成与调试 四、高级使用技巧4.1 指令优化4.2 多…

[HUBUCTF 2022 新生赛]messy_traffic

下载附件 看到文件类型直接用wireshark打开&#xff0c;对MySQL协议进行追踪流&#xff0c;并没有什么发现&#xff0c;后面对NO.437发现有用信息&#xff0c;http追踪流 发现**system(‘cat passwd.txt’);**这里是在打开查看passwd.txt&#xff0c;密码是"SignUpForHUBU…

铁人三项(第五赛区)_2018_rop题解

先启动靶机连接看看。 直接ls&#xff0c;就给我输出句话&#xff0c;看来不能直接拿flag。 那走下流程。 查下位数和其他信息&#xff1a; 可以看到是32位的包&#xff0c;开了NX&#xff0c;但没开其他保护。 用ida32打开looklook。 主函数就是个这&#xff0c;看到了弹出的…