题目描述
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
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 树中的节点数小于 6000 树中的节点数小于6000
- − 100 < = n o d e . v a l < = 100 -100 <= node.val <= 100 −100<=node.val<=100
进阶
- 你只能使用常量级额外空间。
- 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
方法:广度优先搜索
解题思路
广度优先遍历是按层层推进的方式,遍历每一层的节点。广度优先需要用队列作为辅助结构,我们先将根节点放到队列中,然后不断遍历队列。
首先拿出根节点,如果左子树/右子树不为空,就将他们放入队列中。第一遍处理完后,根节点已经从队列中拿走了,而根节点的两个孩子已放入队列中了,现在队列中就有两个节点 2 和 3。
第二次处理,会将 2 和 3 这两个节点从队列中拿走,然后再将 2 和 3 的子节点放入队列中,现在队列中就有四个节点 4,5,6,7。
我们在遍历每一层的时候,用 l a s t N o d e lastNode lastNode 保存上一个节点,遍历到下一个节点时,使 l a s t N o d e lastNode lastNode 的 n e x t next next 指针指向 n o d e node node,便可让每个节点的下一个节点为其右侧节点。
代码
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
queue<Node*> que;
if(root != NULL) que.push(root);
while(!que.empty()) {
int size = que.size();
Node* lastNode;
Node* node;
for(int i = 0; i < size; i++) {
if(i == 0) {
lastNode = que.front();
que.pop();
node = lastNode;
} else {
node = que.front();
que.pop();
lastNode->next = node;
lastNode = node;
}
if(node->left != NULL) que.push(node->left);
if(node->right != NULL) que.push(node->right);
}
}
return root;
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( n ) O(n) O(n)。