(尊重劳动成果,转载请注明出处:https://yangwenqiang.blog.csdn.net/article/details/105928523
冷血之心的博客)
这段时间完成了职业生涯第一次跳槽,对算法题目有了一个更深的认识和理解,这里将二叉树常见的面试题目以及解法补充完善。
二叉树基础题(六):树的子结构&二叉搜索树的判断&镜像二叉树
在本篇博文中,我们介绍再来看两道二叉树相关的高频面试题目吧,如下所示:
- 求二叉树中序遍历的下一个节点
- 求二叉树中两个节点的最低公共祖先节点
题目一:求二叉树中序遍历的下一个节点
给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针(可以使用next表示)。
分析:
画图分析,找一个二叉树。然后我们必须了解何为中序遍历,这里就不展开介绍了。我们可以选择几个二叉树的节点,分析下一个节点有那些规律。总结之后,分情况讨论如下:
- 若当前结点有右子树时,其下一个结点为右子树中最左子结点;
- 若当前结点无右子树时:
- 若当前结点为其父结点的左子结点时,其下一个结点为其父结点;
- 若当前结点为其父结点的右子结点时,继续向上遍历父结点的父结点,直到找到一个结点是其父结点的左子结点(与(1)中判断相同),该结点即为下一结点。
主要是分为了三种情况,依次解决即可:
/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode targetNode){
if(targetNode==null)
return null;
TreeLinkNode cur = null;
// 判断该节点是否有右孩子
if(targetNode.right!=null){
cur = targetNode.right;
while(cur.left!=null){ // 找出其右孩子节点的 最 左边孩子节点
cur = cur.left;
}
return cur;
}
// 若该节点没有右孩子节点,则判断其是否是其父节点的左孩子
if(targetNode.next==null){
return null;
}
if(targetNode==targetNode.next.left){
return targetNode.next;
}
// 此时,该节点既没有右孩子节点,也不是其父节点的左孩子
// 步骤:向上寻找其父节点,直到找到父节点是其父节点的左孩子为此,此时,下一个节点为最后那个父节点
while(targetNode.next!=null){
if(targetNode==targetNode.next.left){
return targetNode.next;
}
// 继续寻找
targetNode = targetNode.next;
}
return null;
}
}
总结:
这个题目说白了,首先需要了解何为中序遍历(这个都不知道,那你别去面试了)。然后需要使用特例法,化抽象为具体,通过对二叉树节点之间的关系进行分析,找到需要处理的三种情况,从而得到解决问题的思路。总之,算法有难度,但是思路还算比较清晰。
题目二:最低公共祖先节点
在一颗二叉树中,求出给定两个节点的最低公共祖先节点!
讨论:如果当前的二叉树是一颗二叉搜索树?
这还有啥好说的,我们找到一个节点,位于两个节点的value值中间即可!代码实现如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null||root==p||root==q)
return root;
if(root.val>p.val&&root.val>q.val)
return lowestCommonAncestor(root.left,p,q);
if(root.val<p.val&&root.val<q.val)
return lowestCommonAncestor(root.right,p,q);
else
return root;
}
}
but, however,如果这是一颗普通的二叉树的?如下所示:
这个时候,需要我们递归的去左右子树上寻找目标节点,(详见代码注释)代码实现如下:
public static BTreeNode getLastCommonNode(BTreeNode pRoot, BTreeNode pLeft, BTreeNode pRight){
//发现目标节点则通过返回值标记该子树发现了某个目标结点
if(pRoot == null || pRoot == pLeft || pRoot == pRight){
return pRoot;
}
//查看左子树中是否有目标结点,没有为null
BTreeNode left = getLastCommonNode(pRoot.left, pLeft, pRight);
//查看右子树是否有目标节点,没有为null
BTreeNode right = getLastCommonNode(pRoot.right, pLeft, pRight);
//都不为空,说明做右子树都有目标结点,则公共祖先就是本身
if(left != null && right != null){
return pRoot;
}
//如果发现了目标节点,则继续向上标记为该目标节点
return left == null ? right : left;
}
总结:
二叉树的下一个节点因为代码量相对较大,考察时候需要更多的时间。所以,在面试中出现的概率相对比较低吧(当然也不排除想头条那种面试时长可达两个小时的,那就随意了)。最低公共祖先节点则是一道各个公司都喜欢考察的二叉树基础题目,校招时候更容易遇到哦~
后续我会继续更新二叉树相关基础题目,感兴趣的同学可以持续关注交流~
注意啦,注意啦~
欢迎大家关注我的牛客专栏:《Java开发岗面试题全解析》 ,点击图片查看详情。
Java开发岗高频面试题全解析,专栏共计32节,已经全部更新完毕。
专栏分9个模块来对Java岗位面试中的知识点进行解析,包括通用面试技能,Java基础,Java进阶,网络协议,常见框架以及算法,设计模式等。
专栏串点成面的解析每个面试题背后的技术原理,由浅入深,循序渐进,力争让大家掌握面试题目的背后的技术原理,摒弃背题模式的陋习。
如果对你有帮助,记得点赞哈,欢迎大家关注我的博客,关注公众号(文强的技术小屋),学习更多技术知识,一起遨游知识海洋~