力扣每日一题0408-429. N 叉树的层序遍历

114 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情 。

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例 1:

image.png

输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]

示例 2:

image.png

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]

广度优先搜索

对于「层序遍历」的题目,我们一般使用广度优先搜索。在广度优先搜索的每一轮中,我们会遍历同一层的所有节点。

具体地,我们首先把根节点 root\textit{root} 放入队列中,随后在广度优先搜索的每一轮中,我们首先记录下当前队列中包含的节点个数(记为 cnt\textit{cnt}),即表示上一层的节点个数。在这之后,我们从队列中依次取出节点,直到取出了上一层的全部 cnt\textit{cnt} 个节点为止。当取出节点 cur\textit{cur} 时,我们将 cur\textit{cur} 的值放入一个临时列表,再将 cur\textit{cur} 的所有子节点全部放入队列中。

当这一轮遍历完成后,临时列表中就存放了当前层所有节点的值。这样一来,当整个广度优先搜索完成后,我们就可以得到层序遍历的结果。

var levelOrder = function(root) {
    if (!root) {
        return [];
    }

    const ans = [];
    const queue = [root];

    while (queue.length) {
        const cnt = queue.length;
        const level = [];
        for (let i = 0; i < cnt; ++i) {
            const cur = queue.shift();
            level.push(cur.val);
            for (const child of cur.children) {
                queue.push(child);
            }
        }
        ans.push(level);
    }

    return ans;
}

深度优先搜索

在 DFS 过程中,虽然对于同层节点并不会被连续处理,但处理顺序仍然满足「从左往后」,因此我们可以使用「哈希表」存储每个深度 depth 对应的节点列表,当处理到节点 uuu 时,将其值添加到其所在的深度列表中。

同时在 DFS 过程中记录下最大深度 max,跑完 DFS后,根据 max 来构建答案。

var levelOrder = function (root) {
    if (!root) return [];
    let ans = []
    var dfs = function (root, degree) {
        if (!root) return null
        if (!ans[degree]) ans[degree] = []
        ans[degree].push(root.val)
        for (const child of root.children) {
            dfs(child, degree + 1)
        }
    }
    dfs(root, 0)
    return ans
};

image.png