LeetCode 👉 HOT 100 👉 二叉树的层序遍历 - 中等题

825 阅读3分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。

题目

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

示例1

输入:root = [3,9,20,null,null,15,7]

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

示例2

输入:root = [1]

输出:[[1]]

示例3

输入:root = []

输出:[]

思路

本题是个二叉树的数据结构,因为二叉树的每个节点,基本都有相同的结构,所以递归的解法是不错的选择。

从例1的结果来看,若 root 具有 n 层,则答案 ans 应具有 n 个元素,且每个元素是数组类型,每个元素里依次存放着按顺序访问的节点值。但是递归的顺序一般都为 DFS(深度优先搜索),即意味着没法按照层的顺序从左到右访问每个节点。

既然递归没法按照顺序访问节点,那可以为每个节点设置一个辅助值 level,代表该节点的层级;然后对于每个节点,按照先访问左子树,再访问右子树的顺序,访问整棵树。根节点,可以视为 第0层

递归完整代码如下

    /**
     * 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)
     * }
     */
    /**
     * @param {TreeNode} root
     * @return {number[][]}
     */
    var levelOrder = function(root) {
        const ans = [];

        const dfs = (root, level) => {
            // 节点为空,结束递归
            if(!root) return;

            // 初始化元素为 []
            if(!ans[level]) {
                ans[level] = [];
            }
            // 按照层级,放入对应的元素中
            ans[level].push(root.val);

            // 将 level + 1,依次访问左、右子树
            dfs(root.left, level + 1);
            dfs(root.right, level + 1);
        }

        // 访问根节点
        dfs(root, 0);

        return ans;
    };

思考: 有没有一种方式,可以按照层级,从左到右依次遍历整棵树呢?

有一种好的方法是,维护一个栈 stack, 先将某个层级的节点入栈,当这个层级入栈都完成后,当前栈里的元素个数,就是当前层级的元素个数;这时,将这些元素依次出栈,出栈时,保存当前节点的数值,同时将节点的左右子树放入栈里。当栈不为空时,就继续这个过程。当栈为空,树也就遍历完成了,且也实现了按照层级顺序,从左到右依次访问节点;

广度优先遍历完整代码

    /**
     * @param {TreeNode} root
     * @return {number[][]}
     */
    var levelOrder = function(root) {
        const ans = [];

        if(!root) {
            return ans;
        }
        
        const stack = [];

        // 根节点入栈
        stack.push(root);

        while(stack.length != 0) {

            // 保存当前层级的节点个数
            const levelSize = stack.length;
            // 先放入初始化的数据结构
            ans.push([]);
            for(let i = 0; i < levelSize; i++) {
                // 栈头出栈
                const node = stack.shift();

                // 访问元素值并保存
                ans[ans.length - 1].push(node.val);

                // 左右节点入栈
                if(node.left) stack.push(node.left);
                if(node.right) stack.push(node.right);
            }
        }

        return ans;
    };

小结

深度优先遍历的算法,一般会用到递归;广度优化的遍历,则一般需要维护一个额外的栈,用于保存当前层级的节点。两种遍历方式的时间复杂度一般都为 O(n),即每个节点都会被访问一次。对于二叉树的遍历,两种遍历方式都需要掌握才行。

LeetCode 👉 HOT 100 👉 二叉树的层序遍历 - 中等题

合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍

如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄