【算法通关村】树的层序遍历—原来如此简单

基本层序遍历与变换

仅输出全部元素

先访问根节点,把其左右孩子放进队列。出队,入队左右孩子。直到队列为空。

 public List<Integer> levelOrder(TreeNode root) {
         
         if(root==null){
             return new ArrayList<>();//List不能被实例化,它是接口,不是class 
         }
         
         LinkedList<TreeNode> queue=new LinkedList<>();
         queue.add(root);
 ​
         List<Integer> res=new ArrayList<Integer>();
         while(queue.size()>0){
             TreeNode t=queue.remove();
             res.add(t.val); //加入的是树节点的值
             if(t.left!=null){
                 queue.add(t.left);
             }
             if(t.right!=null){
                 queue.add(t.right);
             } 
         }
         return res;
     }

由此可见,队列就是一个缓存的作用。

⭐⭐⭐lc102二叉树的层序遍历

将每层的元素分开。

 public List<List<Integer>> levelOrder(TreeNode root) {
         List<List<Integer>> ret=new ArrayList<>();//List不能被实例化,它是接口,不是class
         if(root==null){
             return ret; 
         }
         
         LinkedList<TreeNode> queue=new LinkedList<>();
         queue.add(root);
     
         while(queue.size()>0){
             List<Integer> res=new ArrayList<Integer>();
             int cnt=queue.size();//获取当前队列的长度,即当前这一层的元素个数
             for(int i=1;i<=cnt;i++){
                 TreeNode t=queue.remove();
                 res.add(t.val); //加入的是树节点的值
                 if(t.left!=null){
                     queue.add(t.left);
                 }
                 if(t.right!=null){
                     queue.add(t.right);
                 } 
             }
             ret.add(res);
         }
         
         return ret;
     }
 ​
 //官方的,用到queue
 class Solution {
     public List<List<Integer>> levelOrder(TreeNode root) {
         List<List<Integer>> ret = new ArrayList<List<Integer>>();
         if (root == null) {
             return ret;
         }
 ​
         Queue<TreeNode> queue = new LinkedList<TreeNode>();
         queue.offer(root);
         while (!queue.isEmpty()) {
             List<Integer> level = new ArrayList<Integer>();
             int currentLevelSize = queue.size();
             for (int i = 1; i <= currentLevelSize; ++i) {
                 TreeNode node = queue.poll();
                 level.add(node.val);
                 if (node.left != null) {
                     queue.offer(node.left);
                 }
                 if (node.right != null) {
                     queue.offer(node.right);
                 }
             }
             ret.add(level);
         }
         
         return ret;
     }
 }
lc107自底向上遍历二叉树

在遍历完一层节点之后,将存储该层节点值的列表添加到结果列表的头部。ret.add(0,temp);

在Java中,List 接口有一个 add(int index, E element) 方法,它可以在指定的索引位置插入一个元素 E 到列表中。通过将索引设置为0,你可以将元素插入到列表的开头位置。这就是代码中 ret.add(0, temp) 的实现方式。

 public List<List<Integer>> levelOrderBottom(TreeNode root) {
         List<List<Integer>> ret=new LinkedList<List<Integer>>(); //LinkedList
         if(root==null){
             return ret;
         }
         Queue<TreeNode> queue=new LinkedList<TreeNode>();
         queue.offer(root);
         while(!queue.isEmpty()){
             List<Integer> temp=new ArrayList<Integer>();
             int size=queue.size();
             for(int i=0;i<size;i++){
                 TreeNode t=queue.poll();
                 temp.add(t.val);
                 TreeNode left=t.left,right=t.right;
                 if(left!=null){
                     queue.offer(left);
                 }
                 if(right!=null){
                     queue.offer(right);
                 }
             }
             ret.add(0,temp);
 ​
         }
         return ret;
 ​
     }
lc103锯齿遍历
 public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
         List<List<Integer>> ret=new LinkedList<>();
         if(root==null){
             return ret;
         }
         Queue<TreeNode> queue=new LinkedList<>();  //缓存队列
         queue.offer(root);
         boolean isLeft=true; //加标志位判断
         while(!queue.isEmpty()){
             Deque<Integer> temp=new LinkedList<>(); //层双端队列
             int cnt=queue.size();
             for(int i=0;i<cnt;i++){
                 TreeNode t=queue.poll();
                 if(isLeft){
                     temp.offerLast(t.val); //offerLast
                 } else {
                     temp.offerFirst(t.val); //offerFirst
                 }
                 if(t.left!=null){
                     queue.offer(t.left);
                 }
                 if(t.right!=null){
                     queue.offer(t.right);
                 }
             }
             //Deque<Integer> cannot be converted to List<Integer>
             // ret.add(temp);
             ret.add(new LinkedList<Integer>(temp));
             isLeft=!isLeft;
         }
         return ret;
     }
lc429 N叉树的遍历

和二叉树思路类似,只是每次要把所有孩子入队。

下面是使用 ArrayDeque 作为队列的一些优点:

  1. 性能好: ArrayDeque 的性能通常比 LinkedList 好,尤其是在大部分情况下,因为它是基于数组实现的,随机访问元素的速度更快。

  2. 内存效率: 相对于 LinkedListArrayDeque 使用的内存通常更少,因为它不需要为每个元素存储两个引用(前一个和后一个元素的引用)。

  3. 简单性: ArrayDeque 更容易使用,因为它没有 LinkedList 的额外复杂性。

 public List<List<Integer>> levelOrder(Node root) {
         List<List<Integer>> ret=new ArrayList<>();
         if(root==null){
             return ret;
         }
         Queue<Node> queue=new ArrayDeque<Node>();
         queue.offer(root);
         while(!queue.isEmpty()){
             int cnt=queue.size();
             List<Integer> temp=new ArrayList<>();
             for(int i=0;i<cnt;i++){
                 Node t=queue.poll();
                 temp.add(t.val);
                 for(Node child:t.children){ 
                 //不只是入队左孩子和右孩子了,把所有孩子都入队
                     queue.offer(child);
                 }
             }
             ret.add(temp);
         }
         return ret;
     }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值