输入两棵二叉树A,B,判断B是不是A的子结构。(我们约定空树不是任意一个树的子结构)
假如给定A为{8,8,7,9,2,#,#,#,#,4,7},B为{8,9,2},2个树的结构如下,可以看出B是A的子结构
数据范围:
0 <= A的节点个数 <= 10000
0 <= B的节点个数 <= 10000
{8,8,7,9,2,#,#,#,#,4,7},{8,9,2}true
{1,2,3,4,5},{2,4}true
{1,2,3},{3,1}false
import java.util.*;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
/**
* NC273 树的子结构
* @author d3y1
*/
public class Solution {
private boolean isSubtree = false;
public boolean HasSubtree(TreeNode root1, TreeNode root2){
return solution1(root1, root2);
// return solution2(root1, root2);
}
/**
* 递归: 前序遍历
* @param root1
* @param root2
* @return
*/
private boolean solution1(TreeNode root1, TreeNode root2){
if(root1==null || root2 == null){
return false;
}
preOrder(root1, root2);
return isSubtree;
}
/**
* 前序遍历
* @param root1
* @param root2
*/
private void preOrder(TreeNode root1, TreeNode root2){
if(isSubtree){
return;
}
if(root1 == null){
return;
}
if(root1.val == root2.val){
isSubtree = verify(root1, root2);
}
preOrder(root1.left, root2);
preOrder(root1.right, root2);
}
/**
* 校验: 递归
* @param root1
* @param root2
* @return
*/
private boolean verify(TreeNode root1, TreeNode root2){
if(root2 == null){
return true;
}
if(root1==null || root1.val!=root2.val){
return false;
}else{
return verify(root1.left, root2.left) && verify(root1.right, root2.right);
}
}
/**
* 迭代: 层序遍历
* @param root1
* @param root2
* @return
*/
private boolean solution2(TreeNode root1, TreeNode root2){
if(root1==null || root2 == null){
return false;
}
levelOrder(root1, root2);
return isSubtree;
}
/**
* 层序遍历
* @param root1
* @param root2
*/
private void levelOrder(TreeNode root1, TreeNode root2){
Queue<TreeNode> queue1 = new LinkedList<>();
queue1.offer(root1);
TreeNode node1;
while(!queue1.isEmpty()){
node1 = queue1.poll();
if(node1.val == root2.val){
isSubtree = check(node1, root2);
if(isSubtree){
return;
}
}
if(node1.left != null){
queue1.offer(node1.left);
}
if(node1.right != null){
queue1.offer(node1.right);
}
}
}
/**
* 校验: 队列
* @param root1
* @param root2
* @return
*/
private boolean check(TreeNode root1, TreeNode root2){
Queue<TreeNode> queue1 = new LinkedList<>();
Queue<TreeNode> queue2 = new LinkedList<>();
queue1.offer(root1);
queue2.offer(root2);
TreeNode node1,node2;
while(!queue2.isEmpty()){
node1 = queue1.poll();
node2 = queue2.poll();
if(node1==null || node1.val!=node2.val){
return false;
}
if(node2.left != null){
queue1.offer(node1.left);
queue2.offer(node2.left);
}
if(node2.right != null){
queue1.offer(node1.right);
queue2.offer(node2.right);
}
}
return true;
}
}
import java.util.*;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root2 == null) return false;
dfs(root1, root2);
return flag;
}
boolean flag = false;
private void dfs(TreeNode root1, TreeNode root2) {
if (root1 == null) {
return ;
}
if (flag) {
return ;
}
flag = isSubtree(root1, root2);
if (flag) {
return ;
}
dfs(root1.left, root2);
dfs(root1.right, root2);
}
private boolean isSubtree(TreeNode root1, TreeNode root2) {
if (root2 == null) {
return true;
}
if (root1 == null) {
return false;
}
if (root1.val != root2.val) {
return false;
}
boolean left = isSubtree(root1.left, root2.left);
boolean right = isSubtree(root1.right, root2.right);
return left && right;
}
}
public class Solution {
private boolean JudgeLocContain(TreeNode root1, TreeNode root2) {
//JudgeLocContain方法为‘当前位置包含判断’
//用于比较 ‘A树root1位置的子树’ 是否包含 B树
//且只将B树与‘包括root1节点的 靠上部分的树’进行比较,判断是否包含
if (root1 == null && root2 == null) {
return true;
//root1和root2同时遍历,刚好一起比较完毕,说明root1和root2相同,返回true
}
if (root1 != null && root2 == null) {
return true;
/*此处root2为空代表B树已递归完毕,A树还未完毕,B树与A树之前的结构相同
题中“约定空树不是任意一个树的子结构” 针对 B树这个整体
但该方法是对 A树当前位置子树 和 B树 “逐个节点”校验,而判断是否包含
所以只需要在主方法开始阶段判断B树是否为空即可,此处不必考虑空树约定*/
}
if (root1 == null && root2 != null) {
return false;
} //root1已完毕,root2还未完毕,说明两者不同
//此处隐含的剩下一种情况就是两者都还未完毕(两者都不为空,即可以比较两者值)
if (root1.val != root2.val) {
return false;
}//排除两者值不相等的情况,取相等情况返回递归,保证了之前访问的节点相同
return JudgeLocContain(root1.left, root2.left) &&
JudgeLocContain(root1.right, root2.right);
}
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root2 == null) { //按照约定,判断B树整体是否为空
return false;
}
if (root1 == null) {//root1为空,肯定不包含root2
return false;
}
/*隐含的情况是root1和root2都不为空
进行当前位置包含判断JudgeLocContain,并递归左右子树*/
return JudgeLocContain(root1, root2) || HasSubtree(root1.left, root2) ||
HasSubtree(root1.right, root2);
}
}
public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root2 == null || root1 == null) return false;
if (root2.val == root1.val)
if (HasDirectSubtree(root1.left, root2.left) &&
HasDirectSubtree(root1.right, root2.right)) return true;
return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
/**
判断 root2 是否为 root1 的直接子树
*/
private boolean HasDirectSubtree(TreeNode root1, TreeNode root2) {
if (root1 == null && root2 == null) return true;
else if (root1 == null) return false;
else if (root2 == null) return true;
if (root1.val != root2.val) return false;
return HasDirectSubtree(root1.left, root2.left) &&
HasDirectSubtree(root1.right, root2.right);
}
} 直接子树指的是从根节点开始比较的结果
//可以用双重递归的思想,对于A树的每个节点,判断它是不是和B树是相同的树,如果A有这样的节点,以它开头有和B树完全一样的树,即B是A的子树
public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
//如果root1为空或者root2为空,那么就无法继续递归下去看看有没有子树符合要求了,就直接返回false
if(root1==null || root2==null){
return false;
}
//如果A树中有这么一个root,以它开头的树有一部分和B树完全一样,那么就认为A树包含B树
if(judge(root1,root2)){
return true;
}
//对以A树每个节点开头的树,如果任何一个树满足条件,都会返回true
return HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
}
public boolean judge(TreeNode root1,TreeNode root2){
//同时遍历root1开头的树和B树,如果遍历到B树这个节点为空了,说明之前都没发生过违法行为,返回true
//注意 B树节点为空的时候,A树这个节点是可以有值的
if(root2==null){
//以B树为主,B树是宝宝,整个安全的不返回false的遍历完B树就算成功
return true;
}
//如果走到这了,B树这个节点不为空,那么如果此时A树这个节点为空,那么显然不符合要求
if(root1==null){
return false;
}
//如果走到这个,说明这两个节点同时不为空,那么如果它们的值不相同,它们也不是完全相同的一棵树
if(root1.val!=root2.val){
return false;
}
//这个节点的左子树的每个节点和右子树的每个节点都得符合要求,但凡有一对节点不符合要求返回false的,就整个失败
return judge(root1.left,root2.left) && judge(root1.right, root2.right);
}
} public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root2 == null){
return false;
}
return Same(root1, root2);
}
boolean Same(TreeNode root1,TreeNode root2){
if(root2 == null){
return true;
}
if(root1 == null){
return false;
}
if(root1.val == root2.val){
if(Same(root1.left, root2.left) && Same(root1.right, root2.right))
return true;
}
return Same(root1.left, root2) || Same(root1.right, root2);
}
} public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root2 == null || root1 == null){
return false;
}
if(root1.val == root2.val){
if( (root2.left == null || HasSubtree(root1.left, root2.left)) && (root2.right == null || HasSubtree(root1.right, root2.right))){
return true;
}
}
return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
} public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1==null||root2==null)
return false;
return dps(root1,root2);
}
public boolean dps(TreeNode root1,TreeNode root2){
if(root2==null)
return true;
if(root1==null)
return false;
if(root1.val==root2.val&&dps(root1.left,root2.left)&&dps(root1.right,root2.right))
return true;
else
return dps(root1.left,root2)||dps(root1.right,root2);
}
} public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
//当一个节点存在另一个不存在时
if (root1 == null || root2 == null)
return false;
if (root1.val == root2.val && curd(root1.left, root2.left) &&
curd(root1.right, root2.right)) {
return true;
}
return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
public boolean curd(TreeNode A, TreeNode B) {
if (B == null) {
return true;
}
if (A == null) {
return false;
}
if (A.val == B.val) {
return curd(A.left, B.left) && curd(A.right, B.right);
} else {
return false;
}
}
} public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
//第一步,先确定起始比较位置
if (root1 == null || root2 == null) {
return false;
}
boolean ans = false;
//确立起始比较位置,从该位置尝试比较
if (root1.val == root2.val) {
ans = isSameFromBegin(root1, root2);
}
//说明root1.val != root2.val&nbs***bsp;上面的起始位置不满足需求,换一个起始位置
if (ans != true) {//在左子树中找找
ans = HasSubtree(root1.left, root2);
}
if (ans != true) {//在右子树中找找
ans = HasSubtree(root1.right, root2);
}
return ans;
}
private boolean isSameFromBegin(TreeNode root1, TreeNode root2) {
if (root2 == null) {//roo2为null,说明已经比较完了
return true;
}
if (root1 == null){ //root1为空,说明beginSub不是你的子树
return false;
}
if (root1.val != root2.val){//说明整树中,有不相等的节点
return false;
}
//分别比较左右左右子树,必须都是相等的
return isSameFromBegin(root1.left,root2.left) && isSameFromBegin(root1.right,root2.right);
}
} /**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root1 == null || root2 == null) return false;
return isSame(root1, root2) || HasSubtree(root1.left, root2) ||
HasSubtree(root1.right, root2);
}
public boolean isSame(TreeNode root1, TreeNode root2) {
if (root2 == null) return true;
if (root1 == null || root1.val != root2.val) return false;
return isSame(root1.left, root2.left) && isSame(root1.right, root2.right);
}
} public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1 == null || root2 == null) return false;
return dfs(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
// 不是完全比较两颗树完全相同,而是p覆盖了q
private boolean dfs(TreeNode p, TreeNode q) {
if(q == null) return true;
if(p == null) return false;
if(p.val != q.val) return false;
return dfs(p.left, q.left) && dfs(p.right, q.right);
}
} public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root1 == null || root2 == null)return false;
return trySubtree(root1, root2) || HasSubtree(root1.left, root2) ||
HasSubtree(root1.right, root2);
}
boolean trySubtree(TreeNode p1, TreeNode p2) {
if (p2 == null)return true;
if (p1 == null || p1.val != p2.val)return false;
if (p1.val == p2.val && trySubtree(p1.left, p2.left) &&
trySubtree(p1.right, p2.right))return true;
return false;
}
} public class Solution {
public boolean isSame(TreeNode root1,TreeNode root2){
//如果root2为空,则为true(不需要考虑root1的状况)
if(root2 == null) return true;
if(root1 == null) return false;
//判断首节点的值,然后root1与root2的左子树,然后root1与root2的右子树
return root1.val == root2.val && isSame(root1.left, root2.left) && isSame(root1.right, root2.right);
}
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1 == null || root2 == null) return false;
return isSame(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right,root2);
}
}