OptimalSolution(2)--二叉树问题(4)子树与拓扑结构
一、判断t1树是否包含t2树全部的拓扑结构
1
/ \
2 3 2
/ \ / \ / \
4 5 6 7 4 5
/ \ / /
8 9 10 8 返回:true
解法(O(M×N)):如果t1中某棵子树头结点和t2头结点的值一样,则从这两个头结点开始匹配,匹配的每一步都是让t1上的节点跟着t2的先序遍历移动,每移动一步,都检查t1的当前节点和t2当前节点的值是否一样。如果匹配的过程中发现有不匹配的过程,直接返回false,那么再去寻找t1的下一棵树。
public boolean contains(Node t1, Node t2) {
return check(t1, t2) || contains(t1.left, t2) || contains(t1.right, t2);
}
private boolean check(Node h, Node t2) {
if (t2 == null) return true;
if (h == null || h.val != t2.val) return false;
return check(h.left, t2.left) && check(h.right, t2.right);
}
二、判断t1树中是否有与t2树拓扑结构完全相同的子树
1
/ \
2 3 2 2
/ \ / \ / \ / \
4 5 6 7 4 5 4 5
\ / \ / \
8 9 8 9 返回:true 8 返回:false
如果t1的节点数为N,t2的节点数为M
1.时间复杂度为O(N×M)的方法:对于t1的每棵子树,都去判断是否与t2树的拓扑结构完全一样,这个过程的复杂度为O(M),t1的子树一共有N棵,所以时间复杂度是O(N×M)
做法:(知识扩展:判断两棵树是否相等)首先定义一个判断两棵树是否相等的方法,然后让s的每一个子树都和t作比较,看是否两棵树相等,如果存在相等,那么就返回true
public boolean isSubtree(TreeNode s, TreeNode t) {
if (s == null) return false;
if (isSame(s, t)) return true;
return isSubtree(s.left, t) || isSubtree(s.right, t);
}
private boolean isSame(TreeNode sub, TreeNode t) {
if (sub == null && t == null) return true;
if (sub != null && t != null) {
if (sub.val == t.val) {
if (isSame(sub.left, t.left)) {
if (isSame(sub.right, t.right)) {
return true;
}
}
}
}
return false;
}
2.时间复杂度为O(N+M)的方法:先将t1树前序遍历序列化成字符串“1!2!4!#!8!#!#!5!9!#!#!#!#!3!6!#!#!7!#!#!”,而t2树前序遍历序列化为字符串“2!4!#!8!#!#!5!9!#!#!”(t3树前序遍历序列化为字符串“2!4!#!8!#!#!5!#!#!”),也就是验证t2str是否是t1str的子串即可,可以用KMP算法在线性时间内解决。所以t1序列化的时间复杂度为O(N),t2序列化的时间复杂度是O(M),KMP解决两个字符串的匹配问题O(M+N),所以时间复杂度是O(M+N)。
三、判断一棵树是否为镜像
1
/ \
2 2
/ \ / \
3 4 4 3 true
1
/ \
2 2
\ \
3 3 false
思路很关键:将一棵树分成两棵树判断。
解法:如果两棵树为镜像树,那么必须满足:(1)这两棵树的根节点的值相同(2)第一棵树的左子树是第二棵树的右子树(3)第一棵树的右子树是第一棵树的左子树
1.递归
public boolean isSymmetric(TreeNode root) {
return isSymmetircTwoTrees(root, root);
}
private boolean isSymmetircTwoTrees(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;
return t1.val == t2.val && isSymmetircTwoTrees(t1.left, t2.right) && isSymmetircTwoTrees(t1.right, t2.left);
}
2.迭代(BFS)
public boolean isSymmetricBFS(TreeNode root) {
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode t1 = queue.poll();
TreeNode t2 = queue.poll();
if (t1 == null && t2 == null) continue;
if (t1 == null || t2 == null) return false;
if (t1.val != t2.val) return false;
queue.offer(t1.left);
queue.offer(t2.right);
queue.offer(t1.right);
queue.offer(t2.left);
}
return true;
}
四、二叉树的反转(考虑问题太过复杂,要从最基本的要求开始考虑)
1.仅仅适用于完全二叉树的反转(不满足某个节点有且仅有一个子树为空的情况)
4
/ \
2 7
/ \ / \
1 3 6 9
Output:
4
/ \
7 2
/ \ / \
9 6 3 1
代码实现:
public TreeNode invertTree(TreeNode root) {
if (root != null) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root.left);
queue.offer(root.right);
while (!queue.isEmpty()) {
TreeNode t1 = queue.poll();
TreeNode t2 = queue.poll();
if (t1 == null && t2 == null) continue;
if (t1 != null && t2 != null) {
int tmp1 = t1.val;
t1.val = t2.val;
t2.val = tmp1;
}
queue.offer(t1.left);
queue.offer(t2.right);
queue.offer(t1.right);
queue.offer(t2.left);
}
}
return root;
}
2.适用于所有二叉树的反转
1 1
/ \
2 2
思路1:基于最简单的层序遍历, TreeNode tmp = root.left; root.left = root.right; root.right = tmp;如上面的测试用例,如果root=1,root.left=2,root.right=null,那么在交换之后,还是可以满足,即root.left=null,root.right=2
还要注意的是:必须使用TreeNode cur = queue.poll();作为引用,不能直接使用root = queue.poll();,如果直接使用root,return的是最后一个遍历到的节点。
public TreeNode invertTreeBFS(TreeNode root) {
if (root != null) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()) {
TreeNode cur = queue.poll();
TreeNode tmp = cur.left;
cur.left = cur.right;
cur.right = tmp;
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
}
return root;
}
思路2:基于最简单的后序递归遍历,即invertTreeDFS方法返回root的反转,而root的左子树是右子树的反转,并且root的右子树是左子树的反转。
public TreeNode invertTreeDFS(TreeNode root) {
if (root == null) return null;
TreeNode right = invertTree(root.right);
TreeNode left = invertTree(root.left);
root.left = right;
root.right = left;
return root;
}
OptimalSolution(2)--二叉树问题(4)子树与拓扑结构的更多相关文章
- OptimalSolution(2)--二叉树问题(3)Path路径问题
一.在二叉树中找到累加和为指定值的最长路径长度 给定一棵二叉树和一个32位整数sum,求累加和为sum的最长路径长度.路径是指从某个节点往下,每次最多选择一个孩子节点或者不选所形成的节点链 -3 / ...
- OptimalSolution(2)--二叉树问题(2)BST、BBT、BSBT
一.判断二叉树是否为平衡二叉树(时间复杂度O(N)) 平衡二叉树就是:要么是一棵空树,要么任何一个节点的左右子树高度差的绝对值不超过1. 解法:整个过程为二叉树的后序遍历.对任何一个节点node来说, ...
- OptimalSolution(2)--二叉树问题(1)遍历与查找问题
一.二叉树的按层打印与ZigZag打印 1.按层打印: 1 Level 1 : 1 / \ 2 3 Level 2 : 2 3 / / \ 4 5 6 Level 3 : 4 5 6 / \ 7 8 ...
- ZOJ3805Machine(二叉树左右子树变换)
/* 题意:建立一棵二叉树,左子树和父节点占一个宽度,右子树另外占一个宽度! 使任意左右子树交换顺序,使得整个树的宽度最小! 思路:递归交换左右子树 ! 开始写的代码复杂了,其实左右子树不用真的交换, ...
- 99 Lisp Problems 二叉树(P54~P69)
P54A (*) Check whether a given term represents a binary tree Write a predicate istree which returns ...
- 记忆化搜索 codevs 2241 排序二叉树
codevs 2241 排序二叉树 ★ 输入文件:bstree.in 输出文件:bstree.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 一个边长为n的正三 ...
- 二叉树-你必须要懂!(二叉树相关算法实现-iOS)
这几天详细了解了下二叉树的相关算法,原因是看了唐boy的一篇博客(你会翻转二叉树吗?),还有一篇关于百度的校园招聘面试经历,深刻体会到二叉树的重要性.于是乎,从网上收集并整理了一些关于二叉树的资料,及 ...
- POJ2255二叉树
题目大意就是给出你一个二叉树的前序和中序,要你求后序. 思路:二叉树的排序就是根据根节点的位置来定义的.所以找到二叉树的根节点是最重要的,二叉树的左子树和右子树也可以看成是二叉树,以此递归: #inc ...
- 【数据结构】之二叉树的java实现
转自:http://blog.csdn.net/wuwenxiang91322/article/details/12231657 二叉树的定义: 二叉树是树形结构的一个重要类型.许多实际问题抽象出来的 ...
随机推荐
- java自学小段 产生随机数
public class Suijishu { public static void main(String[] args) { double i=Math.random();//产生一个0-0.5的 ...
- python库之turtle(图形绘制) 开启新的快乐源泉
相信有不少人学习python 都是听了老前辈的推荐 “学python好,python有趣的代码多” 比如说画一只小狮子 这就是今天想要介绍的绘制图形库-turtle 如果也想这样画一只小狮子,或者其他 ...
- Python2与Python3的map()
1. map()函数 Python2中,map(func, seq1[,seq2[...[,seqn)将func作用于seq*的每个序列的索引相同的元素,并最终生成一个[func(seq1[0], s ...
- Cisco交换机、路由器,密码恢复
一.路由器密码恢复 1.重启路由器,同时按下ctrl + breack键中断IOS的加载,路由器进入ROM Monitor模式 2.将配置寄存器的值更改为 0x2142,表示在启动时忽略startup ...
- Centos6 日常使用小结
网络配置目录 1./etc/sysconfig/network-script/ifcfg-eth0 2.netstat -rn Kernel IP routing table Destination ...
- [JavaScript] 《JavaScript高级程序设计》笔记
1.|| 和 && 这两个逻辑运算符和c#是类似的,都是惰性的计算 a() || b() 若a()为真返回a()的结果,此时b()不计算: a()为假则返回b() a() &am ...
- Axure实现百度登录页面(一)
本文主要实现了百度登录页面的设计,其中最主要的是实现点击用户名和密码框时使边框颜色发生变化 (1)首先拖入一个矩形框,将边框可见性全部去掉 (2)将百度的图片拖入,将“用户名密码登录”和“短信快捷登录 ...
- 通过实例理解Java网络IO模型
网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的. 以 ...
- 推荐一款超好用的工具cmder
今天来推荐一个超级好用的命令行工具:cmder 一款Windows环境下非常简洁美观易用的cmd替代者,它支持了大部分的Linux命令.支持ssh连接linux,使用起来非常方便.比起cmd.powe ...
- bs4 UnicodeEncodeError: 'gbk' codec can't encode character '\xa0'
Problem: 写爬虫时,出现了以下错误: 意思是Unicode编码错误,gbk编解码器不能编码\xa0字符. 爬取信息包含中文,使用BeautifulSoup库解析网页,用get_text()方法 ...