(学习资料里面的一道题)
对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同。
给定两棵二叉树的头结点A和B,请返回一个bool值,代表A中是否存在一棵同构于B的子树。
分析:这是一道二叉树相关的练习题,看了老师说的,其实也很简单,这里也就设计到两个方面的知识:二叉树的序列化,KMP算法。。。咋一看可能不清楚为什么需要这两个知识,从头分析,需要判断A树中是否存在B的子树,我们可以把树进行一个前序遍历(图片左边的树为A树,右边的树为B树):A:12453 B:245,我们可以发现A中有245字串和B中的子串相等,发现了这个东西后,再仔细思考是否可以把两个树的子树问题变换为字符串匹配的问题呢,答案是肯定的!但这里还有一个问题,你怎么知道B中的2是一个节点,4是一个节点,5是一个节点的?(举例,A中也这么理解就对了)而不是24是一个节点或者5是一个节点呢?,所以在这样的情况下我们就用到了树的序列化!(比如A树可以使用前序遍历序列化为1!2!4!#!#!5!#!#!3!#!#! 其中!号为分隔符,#号代表空,树的序列化和反序列化不多介绍,看我的代码,或者查资料很快就能理解)
序列化的问题解决,那么问题就很简单了,直接判断A树序列化后的串是否包含B树序列化串,但如何高效呢? 可以采用KMP算法!,这里的KMP算法我参考了tusroy的代码,我把他的gitHub地址帖在这里:
这是gitHub
http://github.com/mission-peace/interview/wiki
这是KMP算法的地址
https://github.com/missionpeace/interview/blob/master/src/com/interview/string/SubstringSearch.java
下面是我写得java代码,其中的KMP算法参考了大神的代码。
package com.gcp.www;
import java.util.LinkedList;
import java.util.Queue;
public class IdenticalTree {
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public boolean chkIdentical(TreeNode A, TreeNode B) {
// write code here
//序列化两个树结构
String aTree = BinaryTreeSerializable(A);
String bTree = BinaryTreeSerializable(B);
//判断a树中是否存在B树序列化后的字符串(KMP算法)
boolean result = KMP(aTree.toCharArray(),bTree.toCharArray());
return result;
}
//二叉树的序列化操作(先序遍历)
public String BinaryTreeSerializable(TreeNode root){
if(root == null){
return "#!";
}
StringBuffer sb = new StringBuffer(root.val + "!");
sb.append(BinaryTreeSerializable(root.left));//
sb.append(BinaryTreeSerializable(root.right));//
return sb.toString();
}
//二叉树的反序列化操作
public TreeNode BinaryTreeDeSerializable(Queue<String> bst){
String val = bst.poll();
if(val.equals("#")){
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(val));
root.left = BinaryTreeDeSerializable(bst);
root.right = BinaryTreeDeSerializable(bst);
return root;
}
/**
* KMP algorithm of pattern matching.
*/
public boolean KMP(char[] text,char[] pattern){
int[] lps = computeTemporaryArray(pattern);
int i = 0;
int j = 0;
while(i < text.length && j < pattern.length){
if(text[i] == pattern[j]){
i++;
j++;
}else{
if(j != 0){
j = lps[j-1];
}else{
i++;
}
}
}
if(j == pattern.length){
return true;
}
return false;
}
/**
*
* Compute temporary array to maintain size of suffix which is same as prefix
* Time/space complexity is O(size of pattern)
*/
private int[] computeTemporaryArray(char[] pattern){
int[] lps = new int[pattern.length];
int index = 0;
for(int i = 1; i < pattern.length;){
if(pattern[index] == pattern[i]){
lps[i] = index+1;
i++;
index++;
}else{
if(index == 0){
lps[i] = 0;
i++;
}else{
index = lps[index-1];
}
}
}
return lps;
}
public static void main(String[] args){
IdenticalTree test = new IdenticalTree();
boolean result = test.KMP("123456".toCharArray(),"346".toCharArray());
System.out.println(result);
}
}
文章浏览阅读408次。 在ubuntu 8.04下安装Oracle 11g2008年05月22日 星期四 11:02oracle 11g 数据库虽然提供了linux x86的版本,但是支持的linux版本只有Red Hat,Novell and Solaris 这几个,debian 和 ubuntu 不在支持之列,所以在ubuntu下安装就相对麻烦一些,请照着下文的方法一步一步的安装,不
文章浏览阅读166次。新东方在线中考网整理了《初一英语下册语法知识点全汇总》,供同学们参考。一. 情态动词can的用法can+动词原形,它不随主语的人称和数而变化。1. 含有can的肯定句:主语+can+谓语动词的原形+其他。2. 含有can的否定句:主语+can't+动词的原形+其他。3. 变一般疑问句时,把can提前:Can+主语+动词原形+其他? 肯定回答:Yes,主语+can。否定回答:No,主语+can't...._七年级下册计算机知识点
文章浏览阅读3k次。在平时开发中,可能会遇到UFUN函数没有的功能,比如创建PTP的加工程序(我目前没找到,哪位大神可以指点一下),可以使用Grip创建PTP,然后用UFUN函数UF_call_grip调用Grip程序。具体如下截图(左侧UFUN,右侧Grip程序):..._uf调用grip
文章浏览阅读156次。第一个:原生普通样式(随着主题不同,样式会变)第二个:原生普通样式-小icon第三个:自定义RatingBar 颜色第四个:自定义RatingBar DrawableRatingBar 各样式实现===============原生样式原生样式其实没什么好说的,使用系统提供的style 即可<RatingBarstyle="?android:attr/ratingBarStyleIndicator"android:layout_width=“wrap_cont.._ratingbar样式修改
文章浏览阅读4.6k次,点赞6次,收藏11次。安装vs2017:参考vs2017下载和安装。安装cmake3.12.3:cmake是一个工程文件生成工具。用户可以使用预定义好的cmake脚本,根据自己的选择(像是Visual Studio, Code::Blocks, Eclipse)生成不同IDE的工程文件。可以从它官方网站的下载页上获取。这里我选择的是Win32安装程序,如图所示:然后就是运行安装程序进行安装就行。配置glfw3...._vs2017的opengl环境搭建(完整篇)
文章浏览阅读976次。MLC NAND,UBIFS_ubifs warning
文章浏览阅读2.2k次。计算机系统的两种存储器形式介绍时间:2016-1-6计算机系统的存储器一般应包括两个部分;一个是包含在计算机主机中的主存储器,简称内存,它直接和运算器,控制器及输入输出设备联系,容量小,但存取速度快,一般只存放那些急需要处理的数据或正在运行的程序;另一个是包含在外设中的外存储器,简称外存,它间接和运算器,控制器联系,存取速度虽然慢,但存储容量大,是用来存放大量暂时还不用的数据和程序,一旦要用时,就..._计算机存储器系统采用的是主辅结构,主存速度快、容量相对较小,用于 1 分 程序,外
文章浏览阅读5.6k次。1. STEP 7(Simatic Manager):STEP 7或者Simatic Manager是西门子PLC编程最常用的软件开发环境。4. STEP 7 MicroWin:STEP 7 MicroWn是一款专门针对微型PLC(S7-200系列PLC)的编程软件,是Simatic Manager的简化版。如果需要与PLC系统配合使用,则需要与PLC编程工具进行配合使用。除了上述软件之外,西门子还提供了一些配套软件和工具,如PLC模拟器、硬件调试工具等,以帮助PLC编程人员快速地进行调试和测试。_西门子plc编程软件
文章浏览阅读36次。【代码】HashMap扩容。_hashma扩容
文章浏览阅读2.9k次。1mvn dependency:copy-dependencies2 项目右键 -> Maven -> Disable Maven Nature3 项目右键 -> Configure -> Convert to Maven Project_maven资源加载不全,怎么重新加载
文章浏览阅读527次。DMLDML的全称是Database management Language,数据库管理语言。主要包括以下操作:insert、delete、update、optimize。本篇对其逐一介绍INSERT数据库表插入数据的方式:1、insert的完整语法:(做项目的过程中将字段名全写上,这样比较容易看懂)单条记录插入语法:insert into table_name (column_name1,......_dml的全称是
文章浏览阅读136次。可以参考: http://git.oschina.net/jrain-group/ 组织下的Java Modbus支持库Modbus-系列文章1、虚拟成对串口(1)下载虚拟串口软件VSPD(可在百度中搜索)image.png(2)打开软件,添加虚拟串口。在设备管理中,看到如下表示添加成功。..._最好用的 modebus调试工具