Medium

题目描述

给定一个二叉树:

struct 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

进阶:

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

解题思路

解题思路

本题是经典的树层次连接问题。与第116题不同的是,这里的二叉树不一定是完美二叉树,因此需要处理更复杂的情况。

方法一:层序遍历(BFS)

使用队列进行层序遍历,对每一层的节点从左到右连接next指针。这是最直观的解法,但需要O(n)的额外空间。

方法二:利用已建立的连接(推荐)

这是O(1)空间复杂度的解法。核心思想是利用上一层已经建立好的next连接来遍历当前层,同时建立下一层的连接。

算法步骤:

  1. 从根节点开始,逐层处理
  2. 对于每一层,使用一个指针遍历该层的所有节点(通过next指针)
  3. 在遍历过程中,将下一层的节点用next指针连接起来
  4. 使用dummy节点技巧简化下一层连接的处理

关键点是维护当前层的遍历指针和下一层的连接指针,通过已有的next连接遍历当前层,同时构建下一层的连接关系。

代码实现

class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return root;
        
        Node* levelStart = root;
        
        while (levelStart) {
            Node* dummy = new Node(0);
            Node* prev = dummy;
            Node* curr = levelStart;
            
            // 遍历当前层,连接下一层
            while (curr) {
                if (curr->left) {
                    prev->next = curr->left;
                    prev = prev->next;
                }
                if (curr->right) {
                    prev->next = curr->right;
                    prev = prev->next;
                }
                curr = curr->next;
            }
            
            levelStart = dummy->next;
            delete dummy;
        }
        
        return root;
    }
};
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        
        level_start = root
        
        while level_start:
            dummy = Node(0)
            prev = dummy
            curr = level_start
            
            # 遍历当前层,连接下一层
            while curr:
                if curr.left:
                    prev.next = curr.left
                    prev = prev.next
                if curr.right:
                    prev.next = curr.right
                    prev = prev.next
                curr = curr.next
            
            level_start = dummy.next
        
        return root
public class Solution {
    public Node Connect(Node root) {
        if (root == null) return root;
        
        Node levelStart = root;
        
        while (levelStart != null) {
            Node dummy = new Node(0);
            Node prev = dummy;
            Node curr = levelStart;
            
            // 遍历当前层,连接下一层
            while (curr != null) {
                if (curr.left != null) {
                    prev.next = curr.left;
                    prev = prev.next;
                }
                if (curr.right != null) {
                    prev.next = curr.right;
                    prev = prev.next;
                }
                curr = curr.next;
            }
            
            levelStart = dummy.next;
        }
        
        return root;
    }
}
var connect = function(root) {
    if (!root) return root;
    
    let levelStart = root;
    
    while (levelStart) {
        let dummy = new _Node(0);
        let prev = dummy;
        let curr = levelStart;
        
        // 遍历当前层,连接下一层
        while (curr) {
            if (curr.left) {
                prev.next = curr.left;
                prev = prev.next;
            }
            if (curr.right) {
                prev.next = curr.right;
                prev = prev.next;
            }
            curr = curr.next;
        }
        
        levelStart = dummy.next;
    }
    
    return root;
};

复杂度分析

复杂度类型说明
时间复杂度O(n)每个节点访问一次
空间复杂度O(1)只使用常量级额外空间

相关题目