剑指offer-树的子结构
题目:树的子结构
题目描述:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:树类的题应该优先考虑用递归解,因为这样简单,理解递归也应该用树这种结构来理解,树这种结构好像天生就自带递归的特点
判断B树是不是A树的子结构,我只需要判断3处
1.B树与A树本身是否相等
2.B树与A树的左子树是否相等
3.B树 与A树的右子树是否相等
这是大的判断方向,具体落实到判断方法时,只需这样判断
1.递归这一层的B为null,直接返回true
2.递归这一层的A为Null,直接返回false
3.如果A,B的当前节点相同,返回判断A,B 树当前节点的左子树,右子树是否分别同时都相同
有不少人看不懂这里的1.递归这一层的B为null,直接返回true,他们认为既然题目要求约定空树不是任意一个树的子结构,那么为什么还要返回true,我觉得这是他们对递归过程缺乏一个形象的认识,这里的1.递归这一层的B为null,直接返回true 与2.递归这一层的A为Null,直接返回false 应该一起看,他是在讲在递归过程中A树完全包含B树,此时上面其他的节点A,B树都相等,B树到了最后一个叶节点的后面,那就说明B树在A树里,那自然要返回true,同理2.递归这一层的A为Null,直接返回false,A,B树的其他节点都已经相等了,,继续判断当前节点,发现我B树的所有节点都没判断完呢,你A树怎么在这里为空了,那么你A树在这里肯定是不能包含我B树的,所以返回fasle
用个图来表示一下
1.递归这一层的B为null,直接返回true
A 1 B 1
/ \ / \
2 3 2 3
/ \ / \
4 5 6 7
可以看出B到3后就已经完了,后面为空表明B树判断完了,所以自然返回true
2.递归这一层的A为Null,直接返回false
A 1 B 1
/ \ / \
2 null 2 3
/ \
4 5
可以看出A中1的右节点为空,而此时B中1的右节点为3,那么此时A这里必然不能包含B,所以返回false,然后让递归转向下一层继续判断
代码;
1 public class Solution { 2 public boolean HasSubtree(TreeNode root1,TreeNode root2) { 3 if(root2==null||root1==null)return false; 4 return isSubtree(root1,root2)||HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2); 5 } 6 private boolean isSubtree(TreeNode root1,TreeNode root2){ 7 if(root2==null)return true; 8 if(root1==null)return false; 9 if(root1.val==root2.val){ 10 return isSubtree( root1.left, root2.left)&&isSubtree( root1.right, root2.right); 11 } 12 else return false; 13 } 14 }