java数据结构与算法刷题-----LeetCode572. 另一棵树的子树(经典题,树字符串化KMP)

news2024/11/16 8:55:31
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

    • 1. 暴力求解,深度优先
    • 2. KMP算法进行串匹配

在这里插入图片描述

1. 暴力求解,深度优先

解题思路:时间复杂度O(s*t)其中s是树的结点个数,t是子树的结点个数。空间复杂度O(max(ds,dt))其中ds是树的深度,dt是子树的深度
  1. 我们先对整个树深度优先遍历
  2. 每个结点都与子树的根节点进行比对
  3. 如果对上了,就以当前结点为根节点,进行和子树的深度优先遍历,看看是否一一对应
  4. 对应上就返回true,没对应上就继续深度优先遍历。直到整个树遍历完成
代码

在这里插入图片描述

class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null && subRoot == null) return true;//如果都为null,就无需找子树了
        else if(root == null || subRoot == null) return false;//如果有一个为null,另一个不是null,肯定不是子树
        //先进行深度优先遍历,直接比对当前结点,如果能对上就可以省下很多时间
        //遍历到底时,再去isSameTree方法中,判断以当前root为根的子树,是否和subRoot是一样的
        else return isSubtree(root.left,subRoot) || isSubtree(root.right,subRoot)||isSameTree(root,subRoot);
    }
    //深度优先判断是否是相同的树
    public boolean isSameTree(TreeNode root,TreeNode subRoot){
        if(root == null && subRoot == null) return true;
        if(root == null || subRoot == null) return false;
        if(root.val == subRoot.val){
            return isSameTree(root.left,subRoot.left) && isSameTree(root.right,subRoot.right);
        }
        return false;
    }
}

2. KMP算法进行串匹配

KMP算法https://blog.csdn.net/grd_java/article/details/136107363
解题思路:时间复杂度O(s+t),空间复杂度O(s+t)
  1. 生成两颗树的遍历序列,以类似如下的形式:(下面形式是广度(层序)遍历序列,需要额外空间辅助,所以我们放弃)
    在这里插入图片描述
  2. 为了效率和更少的空间,我们使用广度优先遍历。那么就需要两个不同的值,来表示某结点左子树为空,和右子树为空的情况。
  3. 同样为了效率,我们不使用字符串比较,选用int型容器,比如int型的链表来生成匹配串
  4. 那么null如何来表示呢?
  1. 我们可以规定两个值,来分别表示左子树为null和右子树为null的情况
  2. 这里我选择先找到树中最大值max,然后令max+1表示左子树为空情况,max+2表示右子树为空情况
  1. 生成两颗树的匹配串后,让大树作为主字符串,要匹配的子树作为要匹配的子串,改编KMP算法,如果匹配成功,说明树中可以匹配到子树
代码:leetcode的特色之一就是,更优的算法,有时因为使用程序自带的特殊容器(比如Java中的List),因为这些容器初始化比较耗时间,反而耗时更高。但是实际工作场景,一旦数据量起来,肯定是这个算法优于上面的暴力解法的。

在这里插入图片描述

class Solution {
    List<Integer> sOrder = new ArrayList<Integer>();//用来保存s树的遍历结果,主串
    List<Integer> tOrder = new ArrayList<Integer>();//保存t树,匹配串
    
    int maxElement, lNull, rNull;//maxElement保存两颗树中最大值,lNull为左子树为空的标记,rNull为右子树为空
    //此方法获取树中最大值,深度优先
    public void getMaxElement(TreeNode t) {
        if (t == null) return;
        maxElement = Math.max(maxElement, t.val);
        getMaxElement(t.left);
        getMaxElement(t.right);
    }
    //此方法生成树的遍历字符串,其中,左右子树为null的,使用lNull和rNull填充
    public void getDfsOrder(TreeNode t, List<Integer> tar) {
        if (t == null) return;
        
        tar.add(t.val);//填充当前值
        //如果左子树为null填充lNull,否则继续遍历左子树
        if (t.left != null) getDfsOrder(t.left, tar);
        else tar.add(lNull);
        //右子树不为null继续遍历右子树,否则填充rNull
        if (t.right != null) getDfsOrder(t.right, tar);
        else tar.add(rNull);
    }
    //入口方法,1.获取树最大值max,并令max+1作为lNull,max+2作为rNull
    //2. 获取两颗树的遍历串。 3. kmp算法进行匹配
    public boolean isSubtree(TreeNode s, TreeNode t) {
        maxElement = Integer.MIN_VALUE;
        //获取两颗树中的最大值
        getMaxElement(s);
        getMaxElement(t);
        //则最大值+1和+2是树中绝对不存在的两个值
        lNull = maxElement + 1;//最大值+1作为左子树为空的填充串
        rNull = maxElement + 2;//最大值+2为右子树为空
        //获取两颗树的遍历串
        getDfsOrder(s, sOrder);
        getDfsOrder(t, tOrder);
        //通过kmp算法
        return kmp();
    }
    //kmp算法,如果匹配到子串,说明树中可以匹配到t这颗子树
    public boolean kmp() {
        int sLen = sOrder.size(), tLen = tOrder.size();
        int[] fail = new int[tOrder.size()];
        fail[0] = 0;
        for (int i = 1, j = 0; i < tLen; ++i) {
            while (j > 0 && !(tOrder.get(i).equals(tOrder.get(j)))) j = fail[j-1];
            if (tOrder.get(i).equals(tOrder.get(j))) ++j;
            fail[i] = j;
        }
        for (int i = 0, j = 0; i < sLen; ++i) {
            while (j > 0 && !(sOrder.get(i).equals(tOrder.get(j)))) j = fail[j-1];
            if (sOrder.get(i).equals(tOrder.get(j))) ++j;
            if (j == tLen) return true;
        }
        return false;
    }
}

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

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

相关文章

Spring-web-Mvc

文章目录 目录 文章目录 前言 1 . 什么是Spring MVC? 1.1 MVC定义 1.2 主要作用 2. Spring MVC 接受响应数据 2.1 RequestMapping注解配置访问路径 2.2 请求 2.2.1 传递单个参数 2.2.2 传递多个参数 2.2.3 传递对象 2.2.4 后端参数重命名&#xff08;后端参数映射…

Linux技巧|centos7|重新认识和学习egrep和grep命令

前言&#xff1a; 相信提高文本检索工具&#xff0c;大家脑海里肯定有很多工具会自动跳出来&#xff0c;比如&#xff0c;grep&#xff0c;egrep&#xff0c;sed&#xff0c;cat&#xff0c;more&#xff0c;less&#xff0c;cut&#xff0c;awk&#xff0c;vim&#xff0c;vi…

Find My扫地机器人|苹果Find My技术与机器人结合,智能防丢,全球定位

扫地机器人又称自动打扫机、智能吸尘、机器人吸尘器等&#xff0c;是智能家电的一种&#xff0c;能凭借人工智能&#xff0c;自动在房间内完成地板清理工作。一般采用刷扫和真空方式&#xff0c;将地面杂物先吸纳进入自身的垃圾收纳盒&#xff0c;从而完成地面清理的功能。现今…

【Vue3】CSS 新特性

:slotted <template> <!-- App.vue--><Son ><div class"a">我要插入了</div></Son> </template><script setup lang"ts"> import Son from ./components/Son.vue </script><style></sty…

最佳实践:Websocket 长连接状态如何保持

WebSocket 是一种支持通过单个 TCP 连接进行全双工通信的协议&#xff0c;相较于传统的 HTTP 协议&#xff0c;它更适合需要实时交互的应用场景。此协议在现代 Web 应用中扮演着至关重要的角色&#xff0c;尤其是在需要实时更新和通信的场合下维持持久连接。本文将探讨 WebSock…

Windows系统误删文件恢复

最近很多用户反馈误删文件的场景比较多.下面华仔将讲解数据恢复的原理和过程.以及一些注意事项。 建议的数据恢复软件 1.EaseUS Data Recovery Wizard(易我数据恢复)需要断网使用 2.Wondershare Recoverit(万兴数据恢复)&#xff0c; Windows系统删除文件原理&#xff1a;如果是…

每周一算法:双向广搜

题目链接 字符串变换 题目描述 已知有两个字串 A , B A,B A,B&#xff0c;及一组字串变换的规则&#xff08;至多 6 6 6个规则&#xff09;: A 1 → B 1 A_1→B_1 A1​→B1​ A 2 → B 2 A_2→B_2 A2​→B2​ … 规则的含义为&#xff1a;在 A A A中的子串 A 1 A_1 A1​…

利用FFMPEG 将RTSP流的音频G711 转码为AAC 并 推流到RTMP

之前我们的视频转码项目中 是没有加入音频的 现在 需要加入音频 &#xff0c;由于RTMP只支持AAC的 音频流 而有的RTSP流的音频编码并不是AAC 大多数都是G711编码 还分为G711A 和G711U 之前用ffmpeg命令行可以直接 完成转码 并推送到RTMP 但是考虑到无法获取更详细的状…

操作系统—xv6内核环境配置

文章目录 xv6内核环境配置1.开发环境的准备(1).如果日常用Linux(2).Windows的回合#1.两个常见方法#2.wsl的一点安装细节#3.记得升级成wsl-2 (3).如果你是macOS#1.一些起因#2.最乐的一集#3.Homebrew的配置#4.mac用户的特权 2.先换apt源3.安装xv6的依赖4.克隆RISC-V GNU 编译器工…

在Centos中用Docker部署oracle-12c

一、介绍 Oracle 12c是Oracle 11g的后续版本。12c代表云计算&#xff08;Cloud Computing&#xff09;&#xff0c;这是Oracle在该版本中强调的一个关键概念。它具有多租户架构、数据库内存、安全增强、大数据管理和自动化管理等功能。它被广泛应用于企业级应用程序和大型数据…

加密与安全_深入了解Hmac算法(消息认证码)

文章目录 PreHMAC概述常见的Hmac算法Code随机的key的生成 KeyGeneratorHmacMD5用Hmac算法取代原有的自定义的加盐算法 HmacMD5 VS MD5HmacSHA256 Pre 加密与安全_深入了解哈希算法中我们提到&#xff0c; 存储用户的哈希口令时&#xff0c;要加盐存储&#xff0c;目的就在于抵…

Zabbix 系统告警“More than 75% used in the configuration cache”处理办法

Zabbix系统报错提示 Zabbix 系统告警“More than 75% used in the configuration cache”&#xff0c;看了一下意思是可用的配置缓存超过75%。 修改缓存大小 vim /etc/zabbix/zabbix_server.confesc : /CacheSize 找到配置 将64M改大一点&#xff0c;保存退出。 重启zabbix…

14.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-数据包分析工具界面与通信设计

内容参考于&#xff1a; 易道云信息技术研究院VIP课 上一个内容&#xff1a;13.如果没有工具就创造工具 码云地址&#xff08;master 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/titan 码云版本号&#xff1a;fef5089bd11dfb86ae8b4e26f25cf59e85f896…

练习 3 Web [ACTF2020 新生赛]Upload

[ACTF2020 新生赛]Upload1 中间有上传文件的地方&#xff0c;试一下一句话木马 txt 不让传txt 另存为tlyjpg&#xff0c;木马文件上传成功 给出了存放目录&#xff1a; Upload Success! Look here~ ./uplo4d/06a9d80f64fded1e542a95e6d530c70a.jpg 下一步尝试改木马文件后缀…

Qt应用软件【测试篇】vargrid内存检查工具

文章目录 vargrid介绍vargrid官网vargrid安装常用命令Valgrind的主要命令vargrid介绍 Valgrind是一个用于构建动态分析工具的框架,能自动检测许多内存管理和线程错误,并详细分析程序性能。Valgrind发行版包括七个成熟工具:内存错误检测器、两个线程错误检测器、缓存和分支预…

autoware.universe中跟踪模块详解,一看就懂!

目录 问题:阅读关键点:总结问题: 根据对预测模块代码的分析,发现预测框出现在点云前方的原因在于跟踪框出现在点云前方 对rviz上的目标进行观察后发现 车辆的检测框先出来一段时间后,跟踪框和预测框同步一块出来 跟踪框总是超出点云一部分 阅读关键点: 每个跟踪器最少要统计…

【JSON2WEB】07 Amis可视化设计器CRUD增删改查

总算到重点中的核心内容&#xff0c;CRUD也就是增删改查&#xff0c;一个设计科学合理的管理信息系统&#xff0c;95%的就是CRUD&#xff0c;达不到这个比例要重新考虑一下你的数据库设计了。 1 新增页面 Step 1 启动amis-editor Setp 2 新增页面 名称和路径随便命名&#xf…

网络安全、信息安全、计算机安全,有何区别?

这三个概念都存在&#xff0c;一般人可能会混为一谈。 究竟它们之间是什么关系&#xff1f;并列&#xff1f;交叉&#xff1f; 可能从广义上来说它们都可以用来表示安全security这样一个笼统的概念。 但如果从狭义上理解&#xff0c;它们应该是有区别的&#xff0c;区别在哪呢&…

08、关于语法:resp?.data?.data 的含义与实际操作中可能遇到的问题

1、数据情况&#xff1a; 其一、从后端拿到的数据为&#xff1a; let resp.data {"data": [],"lag_mode": 3,"totol": 0 }或&#xff1a; let resp.data {"data": [],"totol": 0 }其二、目标数据为&#xff1a; // 想要…

git拉取代码提示403

错误提示信息 remote: Access denied 拒绝访问 fatal: unable to access ‘ https:/ /gitee. cohe requested URL 403解决 找到凭据管理器 找到git的信息&#xff0c;删掉&#xff0c;重新拉取代码&#xff0c;就会提示输入用户名密码