在上一条博客中介绍了一些二叉树的基础操作,今天就来写一些与二叉树相关的基础面试题 :
以下代码中二叉树的节点都是如下的结构:
class Node{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val) {
this.val = val;
}
}
1 . 将二叉树的前序遍历的结果放在一个List中返回
示例:
输入 : [1,null,2,3]
输出 : [1,2,3]
思路 :
① 每次方法递归都要在内存中创建一个新的空间开辟栈帧(栈帧就是包含这次方法调用中的局部变量)
② 某个树的result的内容依赖于左右子树中的遍历结果(左右子树的result)(两个result是不相干的)
③ 先序遍历结果=根节点+左子树的先序结果+右子树的先序结果
public List<Character> preOrderTraversal(Node root) {
List<Character> result = new ArrayList<>();
if (root == null) {
//空树返回空的List 不是null
return result;
}
//访问根节点.此处的访问操作就是把元素添加到result中
result.add(root.val);
//递归访问左子树
result.addAll(preOrderTraversal(root.left));
//递归访问右子树
//把参数中的集合里的所有元素都add到当前集合中
result.addAll(preOrderTraversal(root.right));
return result;
}
注意 :
① addAll 的参数是List , add 的参数是元素
② result 存在的意义是 : 每递归一次都new一个result
③ result.addAll(preOrderTraversal(root.left));可以写成如下的代码:
List<Character> leftResult=preOrderTraversal(root.left);
for(Character x:leftResult){
result.add(x);
}
2 . 将二叉树的中序遍历的结果放在一个List中返回
示例:
输入 : [1,2,3]
输出 : [2,1,3]
public List<Character> inOrderTraversal(Node root) {
List<Character> result = new ArrayList<>();
if (root == null) {
return result;
}
result.addAll(inOrderTraversal(root.left));
result.add(root.val);
result.addAll(inOrderTraversal(root.right));
return result;
}
3 . 将二叉树的后序遍历的结果放在一个List中返回
示例:
输入 : [1,2,3]
输出 : [2,3,1]
public List<Character> postOrderTraveral(Node root){
List<Character> result=new ArrayList<>();
if(root==null){
return result;
}
result.addAll(postOrderTraveral(root.left));
result.addAll(postOrderTraveral(root.right));
result.add(root.val);
return result;
}
4 . 判断两棵树是否相同(结构相同 节点值相同就是相同)
示例 1:
输入 : [1,2,3] , [1,2,3]
输出 : true
示例 2:
输入 : [1,2] , [1,null,2]
输出 : false
思路 :
① 借助递归对问题进行拆分A.val==B.val&&A.left和B.left是否相等&&A.right和B.right是否相等
② 这个代码和先序遍历几乎一模一样 访问操作是比较相等
public boolean isSameTree(Node p,Node q){
if(p==null&&q==null){
//都是空树认为相等
return true;
}
//if((p==null&&q!=null)||(p!=null&&q==null)){
//如果两个树一个为空一个非空,那么最终结果肯定不相等
if(p==null||q==null){
//两种写法都可以 由于前面还有一个 p q 均为空的条件限制
return false;
}
//按照递归的方式把问题拆分
//判断p和q是否相等 => p.val ==q.val&& p.left和q.left相等 &&p.right和q.right相等
return p.val==q.val &&isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}
5 . 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
示例 :
给定的树 s:
3
/ \
4 5
/ \
1 2
/
0
给定的树 t:
4
/ \
1 2
返回 false。
public boolean isSubtree(Node s,Node t){
//先序遍历s这个树,访问到某个节点是时,访问操作就是isSameTree
if(s==null){
return false;
}
//判定s中是否包含t =>先看s和t是否相同||s.left包含t ||s.right包含t
//访问当前节点
return isSameTree(s,t)||
//递归处理左子树
isSubtree(s.left,t)||
//递归处理右子树
isSubtree(s.right,t);
}
6 . 求二叉树的最大深度,二叉树的深度为根节点到最远叶子节点的最长路径上的节点数
示例 :
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
public int maxDepth(Node root){
if(root==null){
return 0;
}
if(root.left==null&&root.right==null){
//叶子节点
return 1;
}
int leftDepth=maxDepth(root.left);
int rightDepth=maxDepth(root.right);
return 1+(leftDepth>rightDepth?leftDepth:rightDepth);
}
注意:
① 代码的执行过程类似于后序遍历 访问根节点的操作是一个稍微复杂一点的计算
② 1+max(左子树的深度,右子树的深度)
7 . 平衡二叉树 , 给定一个二叉树,判断它是否是高度平衡的二叉树 , 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1
示例:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true
思路:
依次遍历每个节点 求节点左右子树高度 计算差值,看这个差值是否符合要求
public boolean isBalanced(Node root){
if(root==null){
return true;
}
if(root.left==null&&root.right==null){
return true;
}
//求左右子树的高度
int leftDepth=maxDepth(root.left);
int rightDepth=maxDepth(root.right);
//左右子树高度差<=1&&左子树平衡&&右子树平衡
return (leftDepth-rightDepth<=1&&leftDepth-rightDepth>=-1)
&&isBalanced(root.left)
&&isBalanced(root.right);
}
8 . 请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
思路 :
① 判定一棵树是不是对称的 ,对应节点值相同 左右子树刚好相反 和根节点没关系
② 主要看左右子树是否对称 左右子树根节点值相等&&左子树.left和右子树.right对称&&左子树.right和右子树.left对称
public boolean isSymmetric(Node root){
if(root==null){
return true;
}
//把判定root是否对称转换成root.left和root.right是否对称
return isMirror(root.left,root.right);
}
private boolean isMirror(Node t1,Node t2){
if(t1==null&&t2==null){
return true;
}
if(t1==null||t2==null){
return false;
}
//判定t1和t2是否对称
return (t1.val==t2.val)&&isMirror(t1.left,t2.right)&&isMirror(t1.right,t2.left);
}
}
以上就是基于二叉树这种数据结构衍生的基础经典面试题,还有很多进阶操作在之后的博客中进行介绍~