二十天刷题计划--填充每个节点的下一个右侧节点指针 II

113 阅读2分钟

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

1.题目

填充每个节点的下一个右侧节点指针 II

给定一个二叉树

struct Node {

int val;

Node *left;

Node *right;

Node *next;

}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

进阶: 你只能使用常量级额外空间。 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。  

示例: 输入:root = [1,2,3,4,5,null,7] 输出:[1,#,2,3,#,4,5,7,#] 解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。  

提示:

树中的节点数小于 6000

-100 <= node.val <= 100


思路

这道题希望我们把二叉树各个层的点组织成链表,一个非常直观的思路是层次遍历。树的层次遍历基于广度优先搜索,它按照层的顺序遍历二叉树,在遍历第 ii 层前,一定会遍历完第 i - 1i−1 层。

算法如下:初始化一个队列 qq,将根结点放入队列中。当队列不为空的时候,记录当前队列大小为 nn,从队列中以此取出 nn 个元素并通过这 nn 个元素拓展新节点。如此循环,直到队列为空。我们不难写出这样的代码:

这样做可以保证每次遍历的 nn 个点都是同一层的。我们可以在遍历每一层的时候修改这一层节点的 next 指针,这样就可以把每一层都组织成链表。


代码

var connect = function(root) {
    if (root === null) {
        return null;
    }
    const queue = [root];
    while (queue.length) {
        const n = queue.length;
        let last = null;
        for (let i = 1; i <= n; ++i) {
            let f = queue.shift();
            if (f.left !== null) {
                queue.push(f.left);
            }
            if (f.right !== null) {
                queue.push(f.right);
            }
            if (i !== 1) {
                last.next = f;
            }
            last = f;
        }
    }
    return root;
};