树的子结构 java_剑指offer:树的子结构(Java)

1.问题描述

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

2.思路

首先根据题目,只有两个树都不为null时才需要进行判断,否则直接返回false。

然后就是遍历大树,找小树的头节点,如果遍历完都没找到,就是false

如果找到小树的头节点,就依次比较后面对应的左右子节点,如果有一个不相等就是false,

一一对应到最后时,肯定是小树的节点为null,大树不一定为null,所以先用小树判断。

如果大树为null了,小树还不是,说明小树不是大树的子结构,返回false。

我觉得难的是遍历大树过程中左子树遍历完成后如何回到根节点,这里使用两个方法,在第二个方法中进行递归遍历根节点一侧的子树,遍历完成后就可以再第一个方法中返回到根节点了。

/**

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) {

boolean result = false; //用来记录判断结果

if(root1 != null && root2 != null){ //只有两个根节点都不为null时才进行判断,否则直接返回false。

result = doesTree1HaveTree2(root1,root2); //调用doesTree1HaveTree2方法判断Tree2是不是Tree1的子结构

if(!result){ //当前两个根节点的值不相等就判断root1的左子节点是否和root2节点相等

result = doesTree1HaveTree2(root1.left,root2);

}

if(!result){ //root1的左子树的节点都和root2不等的情况下判断root1的右子树节点和root2是不是相等。

result = doesTree1HaveTree2(root1.right, root2);

}

}

return result; //root1都遍历完成后返回结果。

}

public boolean doesTree1HaveTree2(TreeNode node1, TreeNode node2){

if(node2 == null){ //如果node2树先遍历完了都和node1对上,说明node2是node1的子结构返回true

return true;

}

if(node1 == null){ //如果node2不为null而node1为null了说名node2不是node1的子结构,返回false

return false;

}

if(node1.val != node2.val){ //只要判断过程中有一个不想等直接返回false,这里注意只是判断一个子树没有匹配的,在HasSubTree中还会判断右子树中是否存在root2结构,所以不会漏掉。

return false;

}

return doesTree1HaveTree2(node1.left, node2.left) && doesTree1HaveTree2(node1.right, node2.right);

//当前节点的值相等,判断左右两个子节点的值是不是相等,有一个不等就返回false。

}

}

注意:

(1)doesTree1HaveTree2方法中判断小树是否为null必须放在前面,不能和判断大树是否为null交换,因为如果换了的话,在大树为null时,小树不确定,小树如果也为null,就应该是true,而这时返回的是false,就是错误的。

(2)如果根节点的左子树中有小树的一部分,而右子树中有整个小树,这种情况不会漏掉,因为在HasSubTree方法中是先判断左子树,在判断右子树,左子树返回false时,会在右子树中重新找小树的根节点,所以不会漏掉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值