二叉树23:树的子结构
来源:互联网 发布:mysql 自定义变量 编辑:程序博客网 时间:2024/05/17 07:21
题目:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:何为子结构,就是具有相同值的结点和结点关系的若干个结点组成的结构。基本思想是保持树B不动,先遍历树A,找到与树B相同的根结点,遍历树A可以使用先序遍历或者其他遍历方式都可以,只需要在遍历结点的代码中添加上判断是否相同的逻辑即可,如果遇到相同的结点node,此时进行判断,即判断在树node中是否包含B,这里可以将判断逻辑封装到一个函数DoesTree1HavaTree2(root1,root2)中,DoesTree1HavaTree2(root1,root2)里面的逻辑是判断在树root1中是否包含树root2,需要判断各个结点是否相同,然后对子节点再次判断新的子树root1中是否包含子树root2(不管root1和root2是否为null都要判断是否包含)。注意要判断的是root1中是否包含root2,而不是root1是否等于root2,先判断root1和root2结点是否满足包含的要求,然后对root1.left和root2.left以及root1.right和root2.right分别进行是否包含的判断。判断2个结点是否包含的逻辑很清晰:如果root2==null,那么不管root1是否==null,都应该是true;如果root1!=null,当root1==null时返回false,当root1!=null&&root2!=null时,判断root1.val与root2.val是否相同,如果不同则返回false,如果相同,则对它们的孩子分别进行包含性的判断,即DoesTree1HavaTree2(root1.left, root2.left)&&DoesTree1HavaTree2(root1.right, root2.right),如果都为true,则表示root1是真正包含root2的。
总结:本题首先对整棵树A进行先序遍历,在遍历代码区域添加if()语句块来判断是否遇到相同的结点,如果遇到相同的结点再进行进一步的判断逻辑,调用DoesTree1HavaTree2(root1,root2)方法判断root1中是否包含root2,这是一个递归方法,会遍历所有结点,直到root2遍历结束,何时结束?当root2==null时就return true。对root1和root2的左右子树分别进行DoesTree1HavaTree2判断,如果都为true则返回true即可。本题需要设计2个递归,一个遍历结点,一个判断2棵树是否具有包含的关系,即在递归里面套递归,但是原理较简单,按照逻辑来解决也不麻烦。
注意:DoesTree1HavaTree2(root1,root2)用来判断树root1是否包含树root2,且此时root1和root2是相同的,之所以在方法体代码中还要判断root1和root2是否相同是对于root1,root2下面的子树之间的包含关系时用的。而题目初始给定的pRoot1和pRoot2是不相同的,因此不能直接使用DoesTree1HavaTree2(pRoot1,pRoot2)来进行判断,要先遍历A找到A中与B相同根结点的结点再调用DoesTree1HavaTree2(root1,root2)进行包含性判断。//给定2个树,判断树B是否是树A的一个子结构:递归遍历找相同根结点--递归判断树是否包含public class Solution { boolean flag; public boolean HasSubtree(TreeNode root1,TreeNode root2) { //特殊输入:空树不是子结构 if(root2==null) return false; //调用递归方法判断root2是否是root1的子结构 this.process(root1,root2); return flag; } //先序遍历二叉树找到和root2相同的结点再进行树的包含性判断 private void process(TreeNode root1,TreeNode root2){ //遍历树A的边界条件 if(root1==null) return; if(root1.val==root2.val){ //根结点相同,需要判断树是否包含 if(this.DoesTree1HavaTree2(root1,root2)){ //如果包含结束,并将flag设置为true,但是递归还是无法结束,必须全部结束 flag=true; return; } } //1:遍历树A的左右子树 if(!flag){ this.process(root1.left,root2); this.process(root1.right,root2); } } //递归方法:判断树root1是否包含树root2 private boolean DoesTree1HavaTree2(TreeNode root1,TreeNode root2){ if(root2==null) return true; else if(root1==null) return false; //此时root1和root2都不为null //先判断root1和root2的值是否相同 if(root1.val!=root2.val) return false; //此时root1==root2,继续判断左右孩子是否包含 boolean left=DoesTree1HavaTree2(root1.left,root2.left); boolean right=DoesTree1HavaTree2(root1.right,root2.right); return left&&right; }}
F1:注意,上面标记处,当flag为true时,说明此时已经找到了B的结构了,于是之后就不希望继续遍历了,如果不加if(!flag){}判断,那么之后的递归this.process(root1.left,root2)和this.process(root1.right,root2)还是会继续进行,即即使已经找到了B的结构,但是还是会将树A中的所有结点都遍历完,这样其实是浪费时间的,因此,添加一个对flag的判断,当flag=true时,因为B已经找到,于是不再遍历其他结点,该返回时就返回。当然不加也不会错,但是最好进行优化,面试时要透露出这个思考过程。
- 二叉树23:树的子结构
- 二叉树的子结构
- 二叉树的子结构
- 二叉树的子结构
- 二叉树的子结构
- 二叉树的子结构
- 二叉树的子结构
- 二叉树的子结构
- 二叉树子结构
- 二叉树的子结构的判定
- 二叉树------树的子结构
- 树的子结构(二叉树)
- 判断二叉树的子结构
- 二叉树的子结构判断
- 20170928_二叉树的子结构
- 重构二叉树&&判断二叉树的子结构
- 【40】二叉树子结构
- 剑指offer-树的子结构 判断二叉树B是不是A的子结构
- oracle函数1
- 好的文章链接收藏
- Sdut 3252 Lowest Unique Price【思维+二分+树状数组】
- 正态分布(Normal distribution)又名高斯分布(Gaussian distribution)
- 最少换站问题
- 二叉树23:树的子结构
- 旧键盘 (20)
- Typescript的三种运行方式
- javascript数组操作用法集合
- 排列序数——详解第五届蓝桥杯决赛题目
- hdu[1041]
- VMware下新手安装Kali Linux
- 大型网站架构之分布式消息队列
- Windows Makefile 使用