LeetCode102-二叉树的层序遍历

Posted Edwin Xu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode102-二叉树的层序遍历相关的知识,希望对你有一定的参考价值。

题目描述

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:

二叉树:[3,9,20,null,null,15,7],
    3
   /   9  20
     /     15  7
返回其层次遍历结果:
[
  [3],
  [9,20],
  [15,7]
]

分析

先考虑只需要返回一个层序遍历结果而不用考虑到底是第几层。如上面只返回[3,9,20,15,7]
我们可以借助于一个队列Q:
首先把根元素放到Q中,while Q不为空时,一个个取出队首,将其不为null的子节点加入队列,直到队列为空。
用上面的例子,先把第一层3加入队列,然后3出队,加入子节点9,20,这是第二次;然后分别取出9,20,加入子节点15,7,这是第三次,取出15,7,他们没有子节点,没有元素入队,队为空,结束。
这个实现是比较简单的:

    //层序 : 利用队列
    public void layerTraversal(TreeNode root) {
        Queue<TreeNode> q= new LinkedBlockingQueue<>();
        TreeNode tmp ;
        q.add(root);
        while (q.size()>0){
            tmp = q.poll();
            System.out.print(tmp.val+" ");
            if (tmp.left!=null)q.add(tmp.left);
            if (tmp.right!=null)q.add(tmp.right);
        }
    }

实际上也可以利用数组,只不过稍微复杂点,原理一样。

    //层序 : 利用数组
    public void layerTraversal_iter_arr(TreeNode root){
        TreeNode []treeNodes= new TreeNode[100];//缺点:难以预测大小,要么浪费空间,要么不足报错
        int in=0,out=0;
        treeNodes[in++]=root;
        while (in>out){
            if (treeNodes[out]!=null){
                System.out.print(treeNodes[out].val+" ");
                treeNodes[in++]=treeNodes[out].left;
                treeNodes[in++]=treeNodes[out].right;
            }
            out++;
        }
    }

现在加需求了:需要考虑层次,即需要把不同层的分开。
我们如何在原来的基础上进行扩展了。
考虑前面使用队列的实现,一个队列存放了所有的元素,不能区分层次。如果使用两个队列存放,那么不同层不就可以交替使用,从而分开了吗?
比如有两个队列Q1、Q2,按上面的例子:

  1. 把root 3放到Q1
  2. Q1中3出队变空,子节点9,20放到Q2
  3. Q2出队变空,9,20的子节点15,7放到Q1
  4. Q1元素全部出队,没有子节点,两个队列都空了,程序结束。

那么现在就好实现了:

辅助双队列

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new LinkedList<>();//结构

        LinkedList<TreeNode> q1 = new LinkedList<>();//Q1
        LinkedList<TreeNode> q2 = new LinkedList<>();//Q2
        LinkedList<TreeNode> cur,empty;//引用,分别指向当前使用的队列和空队列
        TreeNode tmp;
        if (root!=null)q1.add(root); //先把root加入Q1
        while (!q1.isEmpty() || !q2.isEmpty()){//至少一个队列不为空
            List<Integer> level = new LinkedList<>();
            if (q1.isEmpty()){ //使cur指向正在使用的队列,empty指向即将用于存储的空队列
                cur = q2;
                empty = q1;
            }else{
                cur = q1;
                empty= q2;
            }
            while (!cur.isEmpty()){//当前队列不为空,取出所有元素,把元素的非null子节点放到empty队列
                tmp = cur.pop();
                level.add(tmp.val);
                if (tmp.left!=null)empty.add(tmp.left);
                if (tmp.right!=null)empty.add(tmp.right);
            }
            res.add(level);
        }
        return res;
    }

性能:

执行用时 :1 ms, 在所有 Java 提交中击败了91.30%的用户
内存消耗 :39.8 MB, 在所有 Java 提交中击败了5.71%的用户

空间开销有点大,可以考虑使用数组代替队列。

以上是关于LeetCode102-二叉树的层序遍历的主要内容,如果未能解决你的问题,请参考以下文章

leetcode102二叉树的层序遍历

leetcode-102二叉树的层序遍历

#yyds干货盘点# leetcode-102. 二叉树的层序遍历

LeetCode Java刷题笔记—102. 二叉树的层序遍历

LeetCode 102. 二叉树的层序遍历

[JavaScript 刷题] 搜索 - 二叉树的层序遍历, leetcode 102