二叉树基础题(六):树的子结构&二叉搜索树的判断&镜像二叉树
(尊重劳动成果,转载请注明出处:https://yangwenqiang.blog.csdn.net/article/details/105928523
冷血之心的博客)
这段时间完成了职业生涯第一次跳槽,对算法题目有了一个更深的认识和理解,这里将二叉树常见的面试题目以及解法补充完善。
二叉树基础题(六):树的子结构&二叉搜索树的判断&镜像二叉树
今天我们再来看三道二叉树相关的基础题目吧,如下所示:
- 树的子结构
- 二叉搜索树
- 镜像二叉树
题目一:树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:
1、首先设置标志位result = false,因为一旦匹配成功result就设为true,剩下的代码不会执行,如果匹配不成功,默认返回false
2、递归思想,如果根节点相同则递归调用DoesTree1HaveTree2(),如果根节点不相同,则判断tree1的左子树和tree2是否相同,再判断右子树和tree2是否相同
3、注意null的条件,HasSubTree中,如果两棵树都不为空才进行判断,DoesTree1HasTree2中,如果Tree2为空,则说明第二棵树遍历完了,即匹配成功,tree1为空有两种情况:
- 如果tree1为空&&tree2不为空说明不匹配,
- 如果tree1为空,tree2为空,说明匹配。
代码实现如下:
public class Main { public boolean HashSubtree(TreeNode root1, TreeNode root2){ boolean result = false; //当Tree1和Tree2都不为null的时候,才进行比较。否则直接返回false if(root1!=null&&root2!=null){ //如果找到了对应Tree2的根节点的点 if(root1.val==root2.val){ //以这个根节点为为起点判断是否包含Tree2 result = DoesTree1haveTree2(root1,root2); } //如果找不到,那么就再去root的左儿子当作起点,去判断时候包含Tree2 if(!result) result = HashSubtree(root1.left, root2); //如果还找不到,那么就再去root的右儿子当作起点,去判断时候包含Tree2 if(!result) result = HashSubtree(root1.right, root2); } return result; } private boolean DoesTree1haveTree2(TreeNode root1, TreeNode root2) { //如果Tree2已经遍历完了都能对应的上,返回true if(root2==null) return true; //如果Tree2还没有遍历完,Tree1却遍历完了。返回false if(root1==null&&root2!=null) return false; //如果其中有一个点没有对应上,返回false if(root1.val!=root2.val) return false; //如果根节点对应的上,那么就分别去子节点里面匹配 return DoesTree1haveTree2(root1.left, root2.left) &&DoesTree1haveTree2(root1.right, root2.right); } } class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } }
题目二:是否是二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
二叉搜索树的定义如下:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
看到这里,也许大家很easy就可以写出如下的错误代码:
public boolean isValidBST(TreeNode root) { if (root == null) return true; if (root.left != null && root.val <= root.left.val) return false; if (root.right != null && root.val >= root.right.val) return false; return isValidBST(root.left) && isValidBST(root.right); }
这个代码有问题吗?有吗?当然有问题了。我们的当前节点的值要大于左边子树的所有节点,而不仅仅是其一个左子树节点,右边也是同样的道理。比如下边所示并不是一个合法的二叉搜索树,但是我们的算法会返回true
怎么办呢?
这个时候需要使用二叉树操作中经常需要使用的方法了,重载当前的函数,传入更多的参数,使得我们可以拥有更多的信息,最后才是递归调用!
正确的代码实现如下:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public boolean isValidBST(TreeNode root) { return isValidBST(root,null,null); } // 使用辅助函数,增加函数参数列表,在参数中携带额外信息 private boolean isValidBST(TreeNode root, TreeNode min,TreeNode max){ if(root==null) return true; if(min!=null&&root.val<=min.val) return false; if(max!=null&&root.val>=max.val) return false; return isValidBST(root.left,min,root)&&isValidBST(root.right,root,max); } }
题目三:镜像二叉树(二叉树的翻转)
二叉树的镜像:操作给定的二叉树,将其变换为原二叉树的镜像。
思路:
这道题目还算比较简单吧,其实也挺难的,Homebrew 的作者Max Howell面试被 Google
拒啦,因为他不会翻转二叉树。是不是很悲剧?
这道题目可以给出两个解决方法:
- 原地交换当前节点的左右节点
- 新建一颗二叉树
class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } public class Solution { // Mirror求出的即是当前二叉树的镜像 public void Mirror(TreeNode root) { if (root == null) return; // 交换当前节点的左右节点 TreeNode tmpNode = root.left; root.left = root.right; root.right = tmpNode; Mirror(root.left); Mirror(root.right); } // 获取镜像二叉树(不改变原二叉树,重新生成了一个其镜像二叉树) private TreeNode getMirror(TreeNode pRoot) { if (pRoot == null) { return null; } TreeNode root = new TreeNode(pRoot.val); root.right = getMirror(pRoot.left); root.left = getMirror(pRoot.right); return root; } }
总结:
二叉树相关的题目的一个技巧就是重载一个函数用来递归,可以传入额外的参数,获取更多的信息。另外就是二叉树的递归解法中,我们只要定义一个递归函数,并且处理好当前节点要处理的事情即可,别的都交给递归函数,认为其已经给我们解决了问题,切莫在脑子里进行压栈和出栈的操作,因为我们的脑子都不够用哈~
就比如说二叉树的镜像算法中,我们只需要确定下递归结束条件,处理好当前节点的事情(交换),然后再分别递归左右子树即可。
后续我会继续更新二叉树相关基础题目,感兴趣的同学可以持续关注交流~
注意啦,注意啦~
欢迎大家关注我的牛客专栏:《Java开发岗面试题全解析》 ,点击图片查看详情。
Java开发岗高频面试题全解析,专栏共计32节,已经全部更新完毕。
专栏分9个模块来对Java岗位面试中的知识点进行解析,包括通用面试技能,Java基础,Java进阶,网络协议,常见框架以及算法,设计模式等。
专栏串点成面的解析每个面试题背后的技术原理,由浅入深,循序渐进,力争让大家掌握面试题目的背后的技术原理,摒弃背题模式的陋习。
如果对你有帮助,记得点赞哈,欢迎大家关注我的博客,关注公众号(文强的技术小屋),学习更多技术知识,一起遨游知识海洋~
- 【树】二叉树的镜像(递归)、树的子结构(递归)难、从上往下打印二叉树(层次遍历)、二叉搜索树的后序遍历序列(递归)难、二叉树的深度(递归)
- 判断一棵二叉树是不是另一棵的子结构问题
- 二叉树面试题-镜像与判断是否为完全二叉树
- 输入两颗二叉树A,B,判断B是不是A的子结构。
- 判断二叉树平衡/求二叉树的镜像 附属: 一个m*n的矩阵,从左到右从上到下都是递增的,给一个数x,判断x是否在矩阵中
- [PHP] 算法-二叉树的子结构判断的PHP实现
- 输入两棵二叉树A,B,判断B是不是A的子结构。
- python--输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
- 数据结构基础练习-二叉树的镜像
- 判断一棵二叉树是否为另一棵二叉树的子结构(JAVA版本)
- 输入两颗二叉树A,B,判断B是不是A的子结构
- 二叉树--判断一棵二叉树是否是平衡二叉树&&求一颗二叉树的镜像
- 【二叉树】判断一棵二叉树是否是平衡二叉树/求一棵二叉树的镜像/对称的二叉树
- 【二叉树】树的子结构/判断一个节点是否在二叉树中
- 二叉树的子结构判断
- 重建二叉树,二叉树的镜像,二叉搜索树的后序遍历
- 二叉树系列四:Leetcode#98判断二叉树是否为二叉搜索树(BST)
- LeetCode基础--二叉树--判断是否为BST
- 输入两个二叉树A与B,判断B是否是A的子结构
- 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)