js算法:二叉树层序遍历

1,541 阅读3分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

背景

学习前端三个月了,准备刷刷面试题,总结总结,一天几道面试题,向大厂进军。

问题

二叉树的层序遍历

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

示例: 二叉树:[3,9,20,null,null,15,7]

image.png

输出:[[3],[9,20],[15,7]]

解析

我们采用递归遍历:

  1. 创建全局空数组,存放每层的数据。
  2. 从根节点开始遍历,增加层级标记level,默认为0
  3. 每一层创建一个数组,存放左右节点。
  4. 存放每层的数据到全局数组中。
  5. 递归,层级加一
  6. 返回全局数组。

我们来看下代码:

 /**
     * Definition for a binary tree node.
     * function TreeNode(val, left, right) {
     *     this.val = (val===undefined ? 0 : val)
     *     this.left = (left===undefined ? null : left)
     *     this.right = (right===undefined ? null : right)
     * }
     */



    var helpFun=function(root,level,array){
         if(root==null) return;
        if(!array[level]){
            //全局数组中,如果没有初始化改成,创建一层
            array[level]=[];
        }
        // 存放该层的数据。
        array[level].push(root.val);
        //层级+1,递归左边子树
        helpFun(root.left,level+1,array);
        //递归右边子树
        helpFun(root.right,level+1,array);

    }

    /**
     * 入口
     * @param {TreeNode} root
     * @return {number[][]}
     */
    var levelOrder = function(root) {
        if(root==null) return [];
        //全局数组
        var array=[];
        //遍历第一层
        helpFun(root,0,array);
        return array;
    };

验证结果:

image.png

结果验证成功,当我以为就这样完成的时候,突然发现,这也不是层序遍历啊?

层序遍历不应该是一层一层的添加数据吗?? 我们上面代码虽然最终效果输出一样,但是我们的归根到底是深度遍历!

我们用图来表示上面的执行过程。

image.png

既然上面的层序遍历?那我们怎样去实现按层遍历呢??

思路:

  1. 我们还是创建一个全局数组。
  2. 我们在创建一个临时栈,利用栈先进先出的思想。
  3. 将根节点放入栈中。
  4. 循环栈,每循环一遍,变生成一层。
  5. 循环中,从栈中取出一个节点,全局数组保存当前层的节点数组,将下一层的所有节点,全部添加到栈中。
  6. 循环结束,返回全局数组。

我们来看看代码:

    /**
     * Definition for a binary tree node.
     * function TreeNode(val, left, right) {
     *     this.val = (val===undefined ? 0 : val)
     *     this.left = (left===undefined ? null : left)
     *     this.right = (right===undefined ? null : right)
     * }
     */



    var levelOrder = function(root) {
        //全局数组
        const result = [];
        if (!root) {
            return result;
        }
        //临时栈,先进先出
        const stack = [];
        stack.push(root);
        while (stack.length !== 0) {
            //获取当前层所有的节点,用来遍历,也用来标识当前层的节点数量,用来结束该层的循环。
            const currentLevelNodeSize = stack.length;
            //初始化该层的保存节点的数组
            result.push([]);
            for (let i = 1; i <= currentLevelNodeSize; ++i) {
                //弹出一个节点
                const node = stack.shift();
                //全局数组中保存该层的所有节点
                result[result.length - 1].push(node.val);
                //栈中加入下一层的节点
                if (node.left) stack.push(node.left);
                if (node.right) stack.push(node.right);
            }
        }

        return result;
    }

验证结果:

image.png

实现原理图解:

image.png

结语

一步一步慢慢来,踏踏实实把活干!