(尊重劳动成果,转载请注明出处:https://yangwenqiang.blog.csdn.net/article/details/105923803
冷血之心的博客)
这段时间完成了职业生涯第一次跳槽,对算法题目有了一个更深的认识和理解,这里将二叉树常见的面试题目以及解法补充完善。
二叉树基础题(一):先序遍历&中序遍历&后序遍历
二叉树基础题(二):分层遍历&二叉树深度&是否相同的树
二叉树基础题(三):完全二叉树的判断&平衡二叉树的判断
二叉树基础题(四):对称二叉树的判断&之字形分层遍历二叉树
二叉树基础题(五):二叉树的下一个节点&最低公共祖先节点
二叉树基础题(六):树的子结构&二叉搜索树的判断&镜像二叉树
在本篇博客中,我们一起看两个常见面试题目:
我们先来看一个比较笨的方法吧,既然判断是否是对称二叉树,那么只要其本身和其镜像一样,即是一个对称二叉树,所以,我们可以将该二叉树和其镜像就行一个比较即可。
// 方法一:笨方法
public boolean isSymmetrical(TreeNode pRoot) {
// 先求出镜像二叉树
TreeNode node = getMirror(pRoot);
return isSymmetrical(pRoot, node);
}
// 判断两个树是否相等
private boolean isSymmetrical(TreeNode pRoot, TreeNode node) {
if (pRoot == null && node == null) {
return true;
}
if (pRoot == null || node == null) {
return false;
}
if (pRoot.val == node.val) {
return isSymmetrical(pRoot.left, node.left) && isSymmetrical(pRoot.right, node.right);
}
return false;
}
// 获取镜像二叉树
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;
}
这里需要说明的一点是,在二叉树的算法题目中,我们经常需要就行方法的重载,也就是重新定义一个方法,传入更多的参数(信息),这样可以就行有效的递归调用!!!上边就是一个案例。
当然了,我们也可以直接判断当前的二叉树是否是对称二叉树:
可以迭代使用队列来实现,也可以递归比较得出结果:
// 迭代解法,利用成对进出的特性
public boolean isSymmetric(TreeNode root) {
if(root==null)
return true;
Queue<TreeNode> queue = new LinkedList<>();
// 成对进队
queue.add(root.left);
queue.add(root.right);
while(!queue.isEmpty()){
// 成对取出
TreeNode leftNode = queue.remove();
TreeNode rightNode = queue.remove();
if(leftNode==null&&rightNode==null)
continue;
if(leftNode==null||rightNode==null)
return false;
if(leftNode.val==rightNode.val){
// 继续成对进队列
queue.add(leftNode.left);
queue.add(rightNode.right);
queue.add(leftNode.right);
queue.add(rightNode.left);
}else{
return false;
}
}
return true;
}
// 方法2:直接判断是否对称
// 判断是否是对称二叉树,我们可以直接进行对比判断
public boolean isSymmetric2(TreeNode root) {
if(root==null)
return true;
return isSame(root.left,root.right);
}
private boolean isSame(TreeNode p, TreeNode q){
if(p==null&&q==null)
return true;
if(p!=null&&q!=null){
return q.val==p.val&&isSame(p.left,q.right)&&isSame(p.right,q.left);
}
return false;
}
哦,差点忘记了,这里是二叉树的定义:
class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
这个题目考察的分层遍历二叉树的一种变种形式,在最普通的层次遍历中,我们使用了队列来作为辅助数据结构遍历二叉树。
这个题目,我们还是使用队列,但是要充分利用双端队列的特性,即使用其addFirst方法!关键点是要确定当前的层数是奇数层还是偶数层,以此来决定是要将节点添加到队列的队尾还是队头!
代码实现如下:
class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public class Solution {
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
TreeNode r2 = new TreeNode(2);
TreeNode r3 = new TreeNode(3);
TreeNode r4 = new TreeNode(4);
TreeNode r5 = new TreeNode(5);
TreeNode r6 = new TreeNode(6);
TreeNode r7 = new TreeNode(7);
root.left = r2;
root.right = r3;
r2.left = r4;
r2.right = r5;
r3.right = r6;
r3.left = r7;
LinkedList<LinkedList<Integer>> lists = Print(root);
for (int i = 0; i < lists.size(); i++) {
System.out.println(lists.get(i));
}
}
static LinkedList<LinkedList<Integer>> listAll = new LinkedList<LinkedList<Integer>>();
public static LinkedList<LinkedList<Integer> > Print(TreeNode root) {
if(root==null)
return listAll;
LinkedList<Integer> list = new LinkedList<Integer>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
int curLevelNode = 1;
int nextLevelNode = 0;
int depth=1;
TreeNode cur = root;
queue.add(cur);
while(!queue.isEmpty()){
TreeNode node = queue.remove();
curLevelNode--;
if(depth%2==0){
// 双端队列的特性
list.addFirst(node.val);
}else{
list.add(node.val);
}
if(node.left!=null){
queue.add(node.left);
nextLevelNode++;
}
if(node.right!=null){
queue.add(node.right);
nextLevelNode++;
}
if(curLevelNode==0){
curLevelNode = nextLevelNode;
nextLevelNode = 0;
listAll.add(list);
list = new LinkedList<Integer>();
depth++;
}
}
return listAll;
}
}
这里我们借助了https://blog.csdn.net/qq_25827845/article/details/62424798
文中求解二叉树深度时候的一些代码,可以准确判断当前的层数是奇数还是偶数!
因为是第二篇文章中二叉树基础题(二):分层遍历&二叉树深度&是否相同的树
已经有详细的介绍,这里就不展开介绍了。
之字形遍历二叉树是笔者在头条面试中手撕的算法,代码挺长,但是思路比较清晰,整体上看难度不大。对称二叉树判断主要掌握在递归时候重载方法的使用。
后续我会继续更新二叉树相关基础题目,感兴趣的同学可以持续关注交流~
欢迎大家关注我的牛客专栏:《Java开发岗面试题全解析》 ,点击图片查看详情。
Java开发岗高频面试题全解析,专栏共计32节,已经全部更新完毕。
专栏分9个模块来对Java岗位面试中的知识点进行解析,包括通用面试技能,Java基础,Java进阶,网络协议,常见框架以及算法,设计模式等。
专栏串点成面的解析每个面试题背后的技术原理,由浅入深,循序渐进,力争让大家掌握面试题目的背后的技术原理,摒弃背题模式的陋习。
如果对你有帮助,记得点赞哈,欢迎大家关注我的博客,关注公众号(文强的技术小屋),学习更多技术知识,一起遨游知识海洋~