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 二叉树的定义: 二叉树是树形结构的一个重要类型.许多实际问题抽象出来的 ...
随机推荐
- HNU_中小学数学卷子自动生成程序(个人项目)简要分析
一.前言 首先,在这里特别感谢我的结对编程伙伴HnuLyx,他在算法上和设计思路上都与我有很大的不同,个人项目互评中,为我的项目提出了很多很好的建议,让我在认清自己不足的同时,了解到很多以前没有注意的 ...
- SSH Config 管理多主机
使用 一般我们使用ssh连接远程主机的时候,使用命令是: ssh root@ip ssh –i [identity-file] -p [port] user@hostname 但是如果ip地址过多,其 ...
- JAVA线程通信之生产者与消费者
package cn.test.hf.test3; import java.util.concurrent.locks.Condition;import java.util.concurrent.lo ...
- Hadoop点滴-Hadoop分布式文件系统
Hadoop自带HDFS,即 Hadoop Distributed FileSystem(不是HaDoop FileSystem 的简称) 适用范围 超大文件:最新的容量达到PB级 流式数据访问:H ...
- linux 安装docker
1.安装环境 此处在Centos7进行安装,可以使用以下命令查看CentOS版本 lsb_release -a 在 CentOS 7安装docker要求系统为64位.系统内核版本为 3.10 以上,可 ...
- .Net Core 商城微服务项目系列(十一):MQ消费端独立为Window服务+消息处理服务
之前使用MQ的时候是通过封装成dll发布Nuget包来使用,消息的发布和消费都耦合在使用的站点和服务里,这样会造成两个问题: 1.增加服务和站点的压力,因为每次消息的消费就意味着接口的调用,这部分的压 ...
- Openshift yum安装
Openshift yum安装: Yum 安装docker [root@DockerServer openshift]# yum repolist [root@DockerServer openshi ...
- electron教程(四): 使用electron-builder或electron-packager将项目打包为可执行桌面程序(.exe)
我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 子进程管理 electron教程(三): ...
- Windows和Mac系统下安装Docker
在windows和mac系统中使用Docker Desktop安装Docker对系统的要求是很高的. 对于 Windows 系统来说,安装 Docker for Windows 需要符合以下条件: 必 ...
- Xadmin查询
目录 深浅coopy运用 ModelForm的补充 提取模型当中相关属性 getattr和get_field的区别 __ str__,get_field,getattr初识 str ,当用getatt ...