117. 填充每个节点的下一个右侧节点指针 II : 详细图解 O(1) 空间构建过程

题目描述

这是 LeetCode 上的 117. 填充每个节点的下一个右侧节点指针 II ,难度为 中等。

Tag : 「BFS」、「链表」

给定一个二叉树:

ini 复制代码
struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

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

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

示例 1:

css 复制代码
输入:root = [1,2,3,4,5,null,7]

输出:[1,#,2,3,#,4,5,7,#]

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

示例 2:

ini 复制代码
输入:root = []

输出:[]

提示:

  • 树中的节点数在范围 0 , 6000 0, 6000 0,6000 内
  • − 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 −100<=Node.val<=100

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序的隐式栈空间不计入额外空间复杂度。

BFS - 层序遍历

一个最直观的做法,是利用 BFS 对树进行「层序遍历」。

每个 BFS 回合中,对整层节点进行处理。

首先通过 pop 拿到当前节点,同时通过 peek 拿到当前层的下一节点,并建立 next 关系,注意需要跳过每层的最后一个节点。

Java 代码:

Java 复制代码
class Solution {
    public Node connect(Node root) {
        Node ans = root;
        if (root == null) return ans;
        Deque<Node> d = new ArrayDeque<>();
        d.addLast(root);
        while (!d.isEmpty()) {
            int sz = d.size();
            while (sz-- > 0) {
                Node a = d.pollFirst();
                if (sz != 0) a.next = d.peekFirst();
                if (a.left != null) d.addLast(a.left);
                if (a.right != null) d.addLast(a.right);
            }
        }
        return ans;
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    Node* connect(Node* root) {
        Node* ans = root;
        if (root == nullptr) return ans;
        deque<Node*> d;
        d.push_back(root);
        while (!d.empty()) {
            int sz = d.size();
            while (sz-- > 0) {
                Node* a = d.front();
                d.pop_front();
                if (sz != 0) a->next = d.front();
                if (a->left) d.push_back(a->left);
                if (a->right) d.push_back(a->right);
            }
        }
        return ans;
    }
};

Python 代码:

Python 复制代码
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        ans = root
        if root is None:
            return ans
        d = [root]
        while d:
            sz = len(d)
            for i in range(sz):
                a = d.pop(0)
                if i != sz - 1:
                    a.next = d[0]
                if a.left:
                    d.append(a.left)
                if a.right:
                    d.append(a.right)
        return ans

TypeScript 代码:

TypeScript 复制代码
function connect(root: Node | null): Node | null {
    let ans = root;
    if (root == null) return ans;
    const d = [root];
    while (d.length > 0) {
        let sz = d.length;
        while (sz-- > 0) {
            const a = d.shift() as Node;
            if (sz != 0) a.next = d[0];
            if (a.left) d.push(a.left);
            if (a.right) d.push(a.right);
        }
    }
    return ans;
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

BFS - 逐层构建

上述解法中,每一层节点的 next 关系的构建都是独立的。我们构建第 k k k 层的 next 关系时,并没有利用已建好的到第 k − 1 k - 1 k−1 层的 next 关系。

实际上,每一层构建好的 next 关系都可看做「链表」,可参与到下一层 next 关系的构建,同时由于所有节点的起始 next 指向都是 null,相当于首层的 next 关系已经默认建好了。

我们使用图解方式,来感受逐层构建过程:

Java 代码:

Java 复制代码
class Solution {
    public Node connect(Node root) {
        Node ans = root;
        if (root == null) return ans;
        Node cur = root;
        while (cur != null) {
            Node head = new Node(-1), tail = head;
            for (Node i = cur; i != null; i = i.next) {
                if (i.left != null) tail = tail.next = i.left;
                if (i.right != null) tail = tail.next = i.right;
            }
            cur = head.next;
        }
        return ans;
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    Node* connect(Node* root) {
        auto ans = root;
        if (root == nullptr) return ans;
        auto cur = root;
        while (cur) {
            auto head = new Node(-1), tail = head;
            for (auto i = cur; i != nullptr; i = i->next) {
                if (i->left) tail = tail->next = i->left;
                if (i->right) tail = tail->next = i->right;
            }
            cur = head->next;
        }
        return ans;
    }
};

Python 代码:

Python 复制代码
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        ans = root
        if not root:
            return ans
        cur = root
        while cur:
            head = Node(-1)
            tail = head
            i = cur
            while i:
                if i.left:
                    tail.next = i.left
                    tail = tail.next
                if i.right:
                    tail.next = i.right
                    tail = tail.next
                i = i.next
            cur = head.next
        return ans

TypeScript 代码:

TypeScript 复制代码
function connect(root: Node | null): Node | null {
    let ans = root;
    if (root == null) return ans;
    let cur = root;
    while (cur != null) {
        let head = new Node(-1), tail = head;
        for (let i = cur; i != null; i = i.next) {
            if (i.left) tail = tail.next = i.left;
            if (i.right) tail = tail.next = i.right;
        }
        cur = head.next;
    }
    return ans;
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

最后

这是我们「刷穿 LeetCode」系列文章的第 No.117 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour... 。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关推荐
孟健13 分钟前
从5000亿Token到83%字节匹配:AI逆向工程与重构的工程闭环实践
后端·架构·ai编程
IMPYLH23 分钟前
HTML 的 <wbr> 元素
前端·html
Dovis(誓平步青云)44 分钟前
常用命令藏得太深?怎么做一个快捷命令坞
运维·前端·自动化·音视频·prometheus
码事漫谈1 小时前
丢得静悄悄,谈一谈 Agent 的记忆是怎么没的
后端
迪飞特科技1 小时前
智慧物业平台实战:Spring Boot 整合小程序实现报修巡检费用全流程
spring boot·后端·小程序
考虑考虑1 小时前
@JsonInclude注解使用
spring boot·后端·spring
IT_陈寒2 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端
网易云信2 小时前
大模型能上岗做销售吗?我们让 12 款国产模型交了 420 份作业
前端·后端
CCblandy2 小时前
HTTP 长连接 3 类故障实测:[WinError 10053]、99 个 TIME_WAIT、69 次多余握手,4 种对策怎么选
后端·python·网络协议·http·云原生·性能优化·架构
蜗牛互联网2 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python