【Java数据结构】 二叉树经典OJ面试题——刷题笔记+解题思路

简介: 笔记

二叉树的前序遍历


前中后序 遍历 其实方法都一样,就是把节点的访问顺序变一下,代码都一模一样,只是换顺序罢了

题目:

20.png

思路: 本题要求将遍历到的节点放入一个List中返回

  1. 前序遍历顺序:根节点——>左孩子节点——>右孩子节点
  2. 先判断根节点,如果根节点为空,直接返回list
  3. 将当前访问的根节点存入顺序表中
  4. 然后递归访问左孩子节点
  5. 最后递归访问右孩子节点

实现代码:

class Solution {
    List<Integer> list = new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root==null){//根节点空
            return list;//直接返回顺序表
        }
        list.add(root.val);//将当前访问的根节点的值存入顺序表
        preorderTraversal(root.left);//访问左节点
        preorderTraversal(root.right);//访问右节点
        return list;
    }
}


中序遍历


题目:

21.png

思路: 本题要求将遍历到的节点放入一个List中返回

  1. 中序遍历顺序:左孩子节点——>根节点——>右孩子节点
  2. 先判断当前根节点,如果根节点为空,直接返回list
  3. 访问左孩子节点
  4. 将当前访问的根节点值存入顺序表
  5. 最后访问右孩子节点

实现代码:

class Solution {
    List<Integer> list = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        if(root==null){//判断当前根节点是否为空
            return list;
        }
        inorderTraversal(root.left);//访问左孩子节点
        list.add(root.val);//将当前访问的根节点的值存入顺序表
        inorderTraversal(root.right);//访问右孩子节点
        return list;
    }
}

后续遍历

题目:22.png

思路: 本题要求将遍历到的节点放入一个List中返回

  1. 后序遍历顺序:左孩子节点——>右孩子节点——>根节点
  2. 先判断当前根节点,如果根节点为空,直接返回list
  3. 访问左孩子节点
  4. 访问右孩子节点
  5. 最后将当前访问的根节点值存入顺序表

实现代码:

class Solution {
    List<Integer> list = new ArrayList<>();
    public List<Integer> postorderTraversal(TreeNode root) {
         if(root==null){//判断根节点是否为空
            return list;
        }
        postorderTraversal(root.left);//访问左孩子节点
        postorderTraversal(root.right);//访问右孩子节点
        list.add(root.val);//将当前访问的根节点的值存入顺序表
        return list;
    }
}


判断两棵树是否是相同树


题目:

23.png


思路:


首先要明确两棵树相同,指的是左子树和右子树都相同,且值也相同

先判断,两棵树的根节点是否为空,如果两棵树的根节点都是空,那这两棵树相同,直接返回true;

如果两棵树只有一棵树的根节点为空,另一棵树的根节点不为空,那这两棵树必不相同,直接返回false

如果两棵树的根节点都不为空,那就比较其值,如果值不一样,两棵树就不相同,返回false

当以上条件都没返回false,也就是说两棵树的根节点都相同,那么就用 递归 去判断他们的左右孩子节点是否相同,进行套娃,即可

实现代码:

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //2个都为空
        if(p == null && q == null) {
            return true;
        }
        //只有一个不为空
        if(p == null || q == null) {
            return false;
        }
        //都不为空
        if(p.val != q.val) {
            return false;
        }
        //p和q不为空  且对应的值 是相同的  那么去判断两棵树的左树和右树
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }
}


另一棵树是否是当前树的子树


题目:

24.png

思路:

  1. 这题需要自己额外写一个判断是否是相同树的方法参考上一题,实现代码一模一样
  2. 如果当前树的根节点是空,则另一棵树肯定不是它的子树
  3. 如果另一棵树的根节点是空,则肯定是当前树的子树
  4. 每往下递归一个节点,就要判断一次,当前根节点代表的树是否和另一棵树是相同树

25.png

实现代码:

class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if (subRoot == null) return true; //另一棵树的根节点是空,则肯定是当前树的子树
        if (root == null) return false; //当前树的根节点是空,则另一棵树肯定不是它的子树
        return isSubtree(root.left,subRoot)||isSubtree(root.right,subRoot)||isSameTree(root,subRoot);//没往下走一个节点,都要判断一次当前根节点代表的树是否和另一棵树是相同树
    }
     public boolean isSameTree(TreeNode s, TreeNode t) {
        if (s == null && t == null) return true;//都为空
        if (s == null || t == null) return false;//有一个不为空
        if(s.val!=t.val) return false;//值不同,返回false
        //值都相同,继续下一个节点的判断
        return isSameTree(s.left, t.left) && isSameTree(s.right, t.right);
    }
}


求二叉树最大深度


题目:

26.png

思路:


先搞懂一个问题,就是二叉树的深度 = 左子树深度和右子树深度两者取较大值

所以有一个公式,最大深度=左子树深度>右子树深度?左子树深度:右子树深度

利用公式,可以进行递归

先判断当前根节点是否空,空的话返回0(即深度为0)

然后依次判断左子树和右子树的深度

注意:返回的时候要+1,因为根节点也算一层27.png

实现代码:

class Solution {
    public int maxDepth(TreeNode root) {
        if(root==null){//如果根节点空,返回0
            return 0;
        }
        int a=maxDepth(root.left);//求左子树高度
        int b=maxDepth(root.right);//求右子树高度
        return (a > b ? a : b )+ 1;//递归公式
    }
}


判断二叉树是否是平衡二叉树


题目:

29.png思路:

  1. 本题中,一棵高度平衡二叉树定义为:
    一个二叉树每个节点左右两个子树的高度差绝对值不超过 1
  2. 采取从下往上看的思路,额外写一个判断树高度的方法
  3. 判断当前根节点的左子树高度和右子树高度之差的绝对值是否不超过1
  4. 符合平衡条件则返回子树高度,否则返回

实现代码:

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(height(root)>=0)
            return true;
        else 
            return false;
    }
    //从下往上看
    public int height(TreeNode root) {
        if (root == null) //根节点空,返回0
        return 0;
        int left = height(root.left);//获得左节点高度
        if(left == -1) 
        return -1;
        int right = height(root.right);//获得右节点高度
        if(right == -1) 
        return -1;
        return Math.abs(left - right) <=2 ? Math.max(left, right) + 1 : -1;
        //如果左子树和右子树高度差绝对值不大于1,返回子树的高度,否则返回-1
    }
}


判断镜像二叉树


题目:

30.png


思路:

  1. 这道题其实就是判断左右子树是否相同,只不过还需要做一点小小的改动
  2. 因为要判断是不是镜像,所以改动就是 左子树的左孩子值 要等于 右子树的右孩子值,左子树的右孩子值 要等于 右子树的左孩子值

31.png

实现代码:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null){
            return false;  
        }
        return isSame(root.left,root.right);//左右子树符合镜像条件,则是镜像二叉树
    }
    public boolean isSame(TreeNode a,TreeNode b){
        if(a == null && b ==null)
            return true;
        if(a == null || b ==null)
            return false;
        if(a.val != b.val)
            return false;
        //关键在于最后一行代码
        //左子树的左孩子值 要等于 右子树的右孩子值
        //左子树的右孩子值 要等于 右子树的左孩子值
        return isSame(a.left,b.right)&&isSame(a.right,b.left);
    }
}
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
26天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
66 14
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
35 6
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
208 9
|
1月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
35 1
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
1月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
1月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
1月前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
51 4