二叉树的经典面试题
文章目录
- 二叉树的经典面试题
-
- 初阶面试题
-
- 二叉树的最大深度
- 平衡二叉树
- 相同的树
- 另一棵树的子树
- 对称二叉树
- 二叉树的镜像
- 进阶面试题
-
- 把二叉树打印成多行
- 二叉树的最近公共祖先
- 根据二叉树创建字符串
- 总结
再之前我已经发布有关二叉树的基础知识: 二叉树的详解,那么接下来我将会为你们讲一些经典并且常见的二叉树面试题
初阶面试题 二叉树的最大深度
题:二叉树的最大深度
文章图片
解题思路:该题可以使用最为简单的递归方法进行实现,如当根结点为空时返回0,如果不是则继续将其左孩子和右孩子进行递归;
递归如图:
文章图片
代码如下:
class Solution {
public int maxDepth(TreeNode root) {
if(root==null){
//如果该结点为空则返回0
return 0;
}
int leftDepth=maxDepth(root.left);
//递归该结点的左孩子
int rightDepth=maxDepth(root.right);
//递归该结点的右孩子
if(leftDepth>rightDepth){//比较左右的深度,谁大就返回其深度+1;
return leftDepth+1;
}
return rightDepth+1;
}
}
文章图片
其时间复杂度为O(n):其中n是二叉树的结点数并且每一个结点都会被遍历一次,空间复杂度为O(high):其中high是二叉树的高度,因为每使用一次递归需要开辟一个栈空间,而栈的开辟空间取决于递归的深度。
平衡二叉树
平衡二叉树
文章图片
解题思路:由题可知,平衡二叉树指二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。那么我们可以使用递归的方法先求出该节点左子树的深度和右子树的深度,再看其绝对值之差是否小于等于1。
代码如下:
class Solution {
publicint maxDepth(TreeNode root){
if(root==null){
return 0;
}
int left=maxDepth(root.left);
int right=maxDepth(root.right);
return Math.max(left,right)+1;
}
publicboolean isBalanced(TreeNode root) {
if (root==null){
return true;
}
int left=maxDepth(root.left);
int right=maxDepth(root.right);
if (Math.abs(left-right)<=1&&isBalanced(root.right)&&isBalanced(root.left)){
return true;
}
return false;
}
文章图片
其时间复杂度为O(n*n):n为二叉树的结点个数。
空间复杂度为O(n):n 是二叉树中的节点个数。空间复杂度主要取决于递归调用的层数,递归调用的层数不会超过 n。
为了提高时间复杂度效率,可以使用自底向上的递归方法:该方法是先递归判断左右子树是否平衡,最后判断该结点是否为平衡树,如果为则返回高度否则则返回-1
代码如下
class Solution {
public int maxDepth(TreeNode root){
if(root==null){
return 0;
}
int left=maxDepth(root.left);
int right=maxDepth(root.right);
if(left>=0&&right>=0&&Math.abs(left-right)<=1){
return Math.max(left,right)+1;
}
return -1;
}
publicboolean isBalanced(TreeNode root){
return maxDepth(root)>=0;
}
}
文章图片
优化后时间复杂度为O(n)
相同的树
相同的树
文章图片
解题思路:该题使用递归方法可以简单解决,首先我们应该判断该节点是否为空 1.如果p,q都为空则返回true 2.如果p,q只有一个树为空则返回false. 如果p的值不等于q的值则返回false。
核心代码如下:
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q==null){//如果p,q都为空则返回true
return true;
}
if(p==null||q==null){//如果p,q只有一个树为空则返回false
return false;
}
if(p.val!=q.val){//p,q的值不相等
return false;
}
if(isSameTree(p.left,q.left)&&isSameTree(p.right,q.right)){
//递归
return true;
}
return false;
}
}
文章图片
另一棵树的子树
另一棵树的子树
解题思路:其解题方法与上面的题:相同的树大体一样,不过该题得先判断subRoot的根结点是否为root 的根结点还是为root的左孩子或者为root的右孩子。
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q!=null||p!=null&&q==null){
return false;
}
if(p==null&&q==null){
return true;
}
if(p.val!=q.val){
return false;
}
if(isSameTree(p.left,q.left)&&isSameTree(p.right,q.right))
{
return true;
}
return false;
}
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root==null){//判断root是否为空
return false;
}
if(isSameTree(root,subRoot)){
//判断subRoot的根结点是否为root 的根结点
return true;
}
if (isSubtree(root.left,subRoot)){
//subRoot的根结点是否为root 的左孩子
return true;
}
if(isSubtree(root.right,subRoot)){
//subRoot的根结点是否为root 的右孩子
return true;
}
return false;
}
}
文章图片
对称二叉树
对称二叉树
文章图片
解题思路:先判断该树是否为空,再利用递归方法判断左孩子和右孩子的值是否相等。
代码如下:
class Solution {
public boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree){
if(leftTree==null&&rightTree!=null||leftTree!=null&&rightTree==null){
return false;
}
if(leftTree==null&&rightTree==null){
return true;
}
if (leftTree.val!=rightTree.val){
return false;
}
return isSymmetricChild(leftTree.left,rightTree.right)&&isSymmetricChild(leftTree.right,rightTree.left);
}
public boolean isSymmetric(TreeNode root) {
if (root==null){
return false;
}
return isSymmetricChild(root.left,root.right);
}
}
文章图片
二叉树的镜像
二叉树的镜像
文章图片
解题思路:
代码如下:使用递归方法,先判断该树是否为空,再使用递归方法交换左右子树最后返回根节点。
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pRoot TreeNode类
* @return TreeNode类
*/
public TreeNode Mirror (TreeNode pRoot) {
// write code here
if(pRoot==null){
return null;
}
TreeNode root=new TreeNode(pRoot.val);
root.left=Mirror(pRoot.right);
root.right=Mirror(pRoot.left);
return root;
}
}
文章图片
进阶面试题 把二叉树打印成多行
把二叉树打印成多行
文章图片
解题思路:由题可知,其根本是让我们进行二叉树的层次遍历,则我们需要使用队列为了打印出多行则需要将遍历后的值放入集合中
代码如下:
import java.util.*;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}}
*/
public class Solution {
ArrayList > Print(TreeNode pRoot) {
ArrayList> list=new ArrayList<>();
if (pRoot==null){
return list;
}
TreeNode root=pRoot;
Queue queue=new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size= queue.size();
ArrayList list1=new ArrayList<>();
while (size>0){
root=queue.poll();
list1.add(root.val);
if (root.left!=null){
queue.offer(root.left);
}
if(root.right!=null){
queue.offer(root.right);
}
size--;
}
list.add(list1);
}
return list;
}}
文章图片
二叉树的最近公共祖先
二叉树的最近公共祖先
文章图片
解题思路:先判断该根结点是否为空,然后在判断根节点是否等于p或者q,再进行递归左右子树,最后判断左右的数是否为空,都非空返回root,只有一个是非空则返回该结点否则返回空。
代码如下:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null){
return null;
}
if(root==p||root==q){
return root;
}
TreeNode leftTree=lowestCommonAncestor(root.left,p,q);
TreeNode rightTree=lowestCommonAncestor(root.right,p,q);
if(leftTree!=null&&rightTree!=null){
return root;
}
if(leftTree==null&&rightTree!=null){
return rightTree;
}
if(leftTree!=null&&rightTree==null){
return leftTree;
}
return null;
}
}
文章图片
根据二叉树创建字符串
根据二叉树创建字符串
解题思路:该题主要考查先序遍历的实现,不过其也要注意括号的添加,当左孩子为空而右孩子为非空则加一对括号,如果右孩子为空而左孩子为非空则忽略这一对括号。
代码如下:
class Solution {
public void tree2strChild(TreeNode t,StringBuilder sb){
if(t==null){
return;
}
sb.append(t.val);
if(t.left==null){
if(t.right!=null){
sb.append("()");
}
else{
return;
}
}
else if(t.left!=null){
sb.append("(");
tree2strChild(t.left,sb);
sb.append(")");
}
if(t.right==null){
return;
}
else{
sb.append("(");
tree2strChild(t.right,sb);
sb.append(")");
}
}
public String tree2str(TreeNode root) {
if(root==null){
return null;
}
StringBuilder sb=new StringBuilder();
tree2strChild(root,sb);
return sb.toString();
}
}
文章图片
总结 【数据结构|二叉树的经典面试题(你值得拥有)】上述的这些树题,几乎百分之90的题都是使用递归完成,这就要考查我们的思维。
这里也有部分面试题希望对你们有帮助
从前序与中序遍历序列构造二叉树
二叉搜索树与双向链表
文章图片
推荐阅读
- java|写简洁java代码的小技巧
- 图论|WSN连通性模拟、WSN覆盖率模拟、WSN分簇模拟、WSN能量损耗模拟
- android|Android 实现模拟地图定位功能
- 2022年【米哈游】 金三银四 三月内推开始啦!不加班福利好,200+个岗位任你挑选,赶快来看吧!
- 算法|腾讯图像超分辨率算法RealSR,开源了
- 架构师|年后腾讯、阿里、滴滴后台面试题汇总总结 — (含答案)
- 如何写一份优秀的Java程序员简历
- 多线程控制 countDownLatch、CyclicBarrier、Semaphore 总结
- 编程语言|TypeScript的另一面(类型编程)