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


题目:117.填充每个节点的下一个右侧节点指针 II

给定一个二叉树:

class Node {
int val;
Node left;
Node right;
Node next;
}

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

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

  • 示例 1:
输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。
  • 示例 2:
输入:root = []
输出:[]
  • 提示:
树中的节点数在范围 [0, 6000] 内
-100 <= Node.val <= 100
  • 进阶:
你只能使用常量级额外空间。
使用递归解题也符合要求,本题中递归程序的隐式栈空间不计入额外空间复杂度。

思路

要填充二叉树中每个节点的 next 指针,使它指向其右侧节点,可以通过层序遍历来实现。具体的做法是利用广度优先搜索(BFS),逐层遍历树中的节点,并将当前节点的 next 指针指向同一层的下一个节点。如果没有下一个节点,就将 next 指针指向 null

  1. 使用 Queue 来存储每层的节点。
  2. 对每层的节点,除了最后一个节点,其 next 指针应该指向同层的下一个节点。
  3. 最后一个节点的 next 指针应该指向 null
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

代码

public Node connect(Node root) {
    if (root == null) {
        return null;
    }
    // 使用队列进行层序遍历
    Queue<Node> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        // 当前层的节点数
        int size = queue.size();
        Node prev = null;

        for (int i = 0; i < size; i++) {
            Node current = queue.poll();
            // 将前一个节点的 next 指向当前节点
            if (prev != null) {
                prev.next = current;
            }
            prev = current;
            // 将当前节点的子节点加入队列
            if (current.left != null) {
                queue.offer(current.left);
            }
            if (current.right != null) {
                queue.offer(current.right);
            }
        }
        // 当前层最后一个节点的 next 指针指向 null
        prev.next = null;
    }
    return root;
}

思路2

要在常量级别的额外空间内填充二叉树每个节点的 next 指针,使其指向下一个右侧节点,如果没有右侧节点则指向 null。这个问题要求我们不能使用额外的数据结构如队列或栈,因此需要利用树的结构进行原地修改。

  1. 使用当前层的 next 指针

    • 我们可以通过已建立的 next 指针,从左到右遍历每一层。在遍历当前层时,将下一层的节点连接起来。
    • 从树的根节点开始处理,依次处理每一层的节点,将 next 指针正确连接到下一个节点。
  2. 层级遍历

    • 在每一层的遍历中,通过 next 指针遍历该层的所有节点,并连接其左右子节点。
    • 使用两个指针:current 用于遍历当前层,nextLevel 用于记录下一层的起始节点。
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

代码

public Node connect(Node root) {
    Node dummy = new Node();
    Node current = root;
    // 遍历每一层
    while (current != null) {
        dummy.next = null;
        // 下一层的链表
        Node nextLevel = dummy;
        // 遍历当前层的链表
        while (current != null) {
            if (current.left != null) {
                // 下一层的相邻节点连起来
                nextLevel.next = current.left;
                nextLevel = nextLevel.next;
            }
            if (current.right != null) {
                // 下一层的相邻节点连起来
                nextLevel.next = current.right;
                nextLevel = nextLevel.next;
            }
            // 当前层链表的下一个节点
            current = current.next;
        }
        // 下一层链表的头节点
        current = dummy.next;
    }
    return root;
}

文章作者: cxyexe
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 cxyexe !
  目录