一次字节面试,被二叉树的层序遍历捏爆了

简介: 大家好,我是bigsai,在数据结构与算法中,二叉树无论是考研、笔试都是非常高频的考点内容,在二叉树中,二叉树的遍历又是非常重要的知识点,今天给大家讲讲二叉树的层序遍历。

前言



大家好,我是bigsai,在数据结构与算法中,二叉树无论是考研、笔试都是非常高频的考点内容,在二叉树中,二叉树的遍历又是非常重要的知识点,今天给大家讲讲二叉树的层序遍历。


这部分很多人可能会但是需要注重一下细节。


前面介绍了二叉排序树的构造和基本方法的实现,遍历也是比较重要的一环,并且二叉树的层序遍历也是bfs的最简单情况,这里我就将二叉树的层序遍历以及常考问题给大家分享一下。


在了解二叉树的遍历之前,需要具备数据结构与算法有队列、递归、栈、二叉树,这些内容咱们前面都有讲过,有这方面知识欠缺的同学可以往前翻一翻看一看!


层序遍历



6dfbb8a9af1fa48d85bf01bb904aacd2.png


层序遍历,听名字也知道是按层遍历。一个节点有左右节点,按层处理就是当前层兄弟节点的优先级要大于子节点处理的优先级,所以就是要将子节点放到后面处理,这就适合队列这个数据结构用来存储。


对于队列,先进先出。从root节点push到队列,那么队列中先出来的顺序是第二层的左右(假设都有),第二层每个节点执行的时候按照左右顺序添加到队列,第三层的节点就会有序的放到最后面……按照这样的规则就能得到一个层序遍历的顺序。


实现的代码也很容易理解:


public int[] levelOrder(TreeNode root) {
        int arr[]=new int[10000];
        int index=0;
        Queue<TreeNode>queue=new ArrayDeque<>();
        if(root!=null)
            queue.add(root);
        while (!queue.isEmpty()){
            TreeNode node=queue.poll();
            arr[index++]= node.val;
            if(node.left!=null)
                queue.add(node.left);
            if(node.right!=null)
                queue.add(node.right);
        }
        return Arrays.copyOf(arr,index);
    }


分层存储



但是在具体笔试他可能要求你分层存储,例如力扣的102二叉树的层序遍历,要求返回一个List<List<Integer>>类型。


012caf73c7795b78da8989d07b4276c5.png


这种相比上面一个多了一层逻辑就是每一层数据放到一块,这个也很容易,最好想到的就是两个队列(容器)一层一层遍历存储,然后交替,但是两个队列(容器)的写法常常会被面试官嫌弃,很多面试官让你想想怎么不用两个容器实现?


不用双队列去枚举结果也很容易,重要的就是先记录队列大小size(当前层节点数量),然后执行size次数的枚举即可,具体代码为:


public List<List<Integer>> levelOrder(TreeNode root) {
  List<List<Integer>>list=new ArrayList<List<Integer>>();
  if(root==null)return list;
  Queue<TreeNode>q1=new ArrayDeque<TreeNode>();
  q1.add(root);
  while (!q1.isEmpty()) {
    int size=q1.size();
    List<Integer>value=new ArrayList<Integer>();
    for(int i=0;i<size;i++)
    {
      TreeNode pNode=q1.poll();
      if(pNode.left!=null)
        q1.add(pNode.left);
      if(pNode.right!=null)
        q1.add(pNode.right);
      value.add(pNode.val);
    }
    list.add(value);
  }
  return list;
}


之字形打印



除了这个直接层序遍历,二叉树还有很高频的就是之字形遍历,例如剑指offer32和力扣103 二叉树的锯齿形层序遍历,它的题目要求为:


请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。


这道题虽然不是难题,但是有点绕,本来队列这玩意我们就要大脑想一下什么顺序,又出来一个之字形,属实增加的思维逻辑,有不少小伙伴反映当时面试官让手撕这道题,自己以前明明写过,但是太紧张自己给自己绕进去了!


1bdc8c6440b970057847decd51aaede6.png


其实这个问题也很容易转化,因为值只是存储,我们按照老样子去进行层序遍历,只不过在遍历时候通过当前层奇偶数来给它判断是从左往右存储到结果中还是从右往左放到结果中。当然,判断奇数偶数也很容易,可以用变量,也可以用结果List的size()都可。


个人实现的一个朴素代码为:


public List<List<Integer>> levelOrder(TreeNode root) {
  List<List<Integer>> value=new ArrayList<>();//存储到的最终结果
  if(root==null)
    return value;
  int index=0;//判断
  Queue<TreeNode>queue=new ArrayDeque<>();
  queue.add(root);
  while (!queue.isEmpty()){
    List<Integer>va=new ArrayList<>();//临时 用于存储到value中
    int len=queue.size();//当前层的数量
    for(int i=0;i<len;i++){
      TreeNode node=queue.poll();
      if(index%2==0)
        va.add(node.val);
      else
        va.add(0,node.val);
      if(node.left!=null)
        queue.add(node.left);
      if(node.right!=null)
        queue.add(node.right);
    }
    value.add(va);
    index++;
  }
  return value;
}


上面实现代码也仅使用一个队列,不过这个问题可能有很多更巧妙的解法需要大家自己去挖掘。


结语



二叉树的层序遍历是二叉树内容中较为简单的内容,但是层序遍历尤其是之字形遍历(锯齿形遍历)出现的频率真的太高了,并且最好是掌握比较好的方法不要显得太臃肿。


不过在实际遇到问题时候,能AC是第一位,然后才是精简的逻辑和骚气的代码。


二叉树层序遍历变种问题不多,掌握上面三个问题基本就够了,而二叉树的前序、中序、后序遍历(递归非递归)考察非常多,后面会给大家加快梳理总结,敬请期待!


如果文章对你有帮助,欢迎关注我↓,回复【666】免费获得我自己的原创pdf! 咱们下次再见!


目录
相关文章
|
24天前
|
Arthas Kubernetes Java
字节面试:CPU被打满了,CPU100%,如何处理?
尼恩,一位拥有20多年经验的老架构师,针对近期读者在一线互联网企业面试中遇到的CPU 100%和红包架构等问题,进行了系统化梳理。文章详细解析了CPU 100%的三大类型问题(业务类、并发类、内存类)及其九种常见场景,提供了使用jstack和arthas两大工具定位问题的具体步骤,并分享了解决死锁问题的实战案例。尼恩还强调了面试时应先考虑回滚版本,再使用工具定位问题的重要性。此外,尼恩提供了丰富的技术资料,如《尼恩Java面试宝典》等,帮助读者提升技术水平,轻松应对面试挑战。
字节面试:CPU被打满了,CPU100%,如何处理?
|
29天前
|
Java API 对象存储
JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
|
2月前
|
算法
二叉树面试题
本文介绍了二叉树相关的几个经典算法问题。首先讲解了如何判断两棵树是否完全相同(LeetCode 100),并给出了代码示例。接着讨论了如何判断一棵树是否是另一棵树的子树(LeetCode 572),详细分析了子树的定义及判断方法。然后介绍了翻转二叉树(LeetCode 226)的实现方法,即在遍历时交换每个节点的左右子树。随后探讨了如何判断一棵树是否是对称的(LeetCode 101),通过对左右子树的递归比较来实现。最后分析了平衡二叉树的概念(LeetCode 110)及判断方法,并给出了优化后的代码示例。此外,还简要介绍了二叉树遍历及二叉树最近公共祖先(LeetCode 236)的问题
27 6
二叉树面试题
|
13天前
|
算法 Java
JAVA 二叉树面试题
JAVA 二叉树面试题
13 0
|
5月前
|
SQL 关系型数据库 MySQL
字节面试:MySQL自增ID用完会怎样?
字节面试:MySQL自增ID用完会怎样?
69 0
字节面试:MySQL自增ID用完会怎样?
|
5月前
|
存储 Java 容器
研二学妹面试字节,竟倒在了ThreadLocal上,这是不要应届生还是不要女生啊?
【6月更文挑战第1天】研二学妹面试字节,竟倒在了ThreadLocal上,这是不要应届生还是不要女生啊?
46 5
|
4月前
|
前端开发 数据挖掘
字节面试:领域、子域、核心域、通用域和支撑域怎么划分?
领域驱动设计(DDD)通过划分业务领域和子域简化复杂性。领域是业务问题的范围,子域是更小的专业部分。核心域代表业务的核心竞争力,如电商中的商品、订单和支付;通用域提供跨领域服务,如用户管理;支撑域支持核心功能,如物流、客服和数据分析。这种划分帮助团队专注关键业务,提高开发效率和软件对业务需求的契合度。
186 0
|
6月前
|
设计模式 网络协议 算法
9次Android面试经验总结,已收字节,阿里(1),费时6个月成功入职阿里
9次Android面试经验总结,已收字节,阿里(1),费时6个月成功入职阿里
|
6月前
【一刷《剑指Offer》】面试题 23:从上往下打印二叉树
【一刷《剑指Offer》】面试题 23:从上往下打印二叉树
|
6月前
【一刷《剑指Offer》】面试题 19:二叉树的镜像
【一刷《剑指Offer》】面试题 19:二叉树的镜像