题目
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL
。
初始状态下,所有 next 指针都被设置为 NULL
。
例子:
输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。
解题思路
-
理解:题目要求在一个完美二叉树中,填充每个节点的
next
指针,使其指向右侧的下一个节点,如果不存在则指向NULL
。 -
使用层序遍历:由于是完美二叉树,每一层的节点可以看作是一个连续的序列,因此可以使用层序遍历来填充
next
指针。 -
连接同一层的节点:在每一层中,从左到右遍历节点,将每个节点的左子节点连接到右子节点,并将右子节点的
next
指针连接到下一层的左子节点。
解题过程
-
初始化:检查根节点是否为空,如果为空则直接返回
null
。 -
记录每层最左节点:使用
leftMost
指针记录每一层的最左节点。 -
逐层遍历:使用一个外部
while
循环来逐层遍历树,直到达到叶子节点。 -
同层连接:在每一层内部,使用一个内部
while
循环来连接同一层的节点。将当前节点的左子节点的next
指针指向右子节点,如果当前节点有next
节点,则将右子节点的next
指针指向next
节点的左子节点。 -
移动到下一层:完成一层的所有连接后,将
leftMost
移动到下一层的最左节点,即当前leftMost
的左子节点。 -
返回根节点:遍历完成后,返回根节点。
复杂度
-
时间复杂度:O(n),其中n是二叉树中的节点数。每个节点恰好被访问一次。
-
空间复杂度:O(1)
Code
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
if (root == null) {
return null;
}
Node leftMost = root;
while (leftMost.left != null) {
Node node = leftMost;
while (node != null) {
node.left.next = node.right;
if (node.next != null) {
node.right.next = node.next.left;
}
node = node.next;
}
leftMost = leftMost.left;
}
return root;
}
}
题目
给定一个二叉树:
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 指针连接),'#' 表示每层的末尾。
解题思路
-
初始化:根节点的
next
指针指向NULL
。 -
层序遍历:使用队列进行层序遍历,将同一层次的节点放入同一个队列中。
-
连接同一层的节点:对于每一层,按照从左到右的顺序将节点放入队列,然后将队列中的节点依次连接起来。
-
处理下一层的开始:在每一层的末尾,将最后一个节点的右子节点连接到下一层的第一个节点(如果是非空的话)。
解题过程
-
创建队列:使用队列存储当前层的节点。
-
添加根节点:如果根节点不是
null
,则将其添加到队列中。 -
层序遍历:当队列非空时,执行以下操作:
-
取出队列的第一个节点作为当前节点。
-
如果当前节点的前一个节点不是
null
,则将当前节点设置为前一个节点的next
。 -
如果当前节点的左子节点不是
null
,则将其添加到队列中。 -
如果当前节点的右子节点不是
null
,则将其添加到队列中,并且设置其next
指针指向下一层的第一个节点(如果存在的话)。
-
-
设置末尾节点的
next
:在每一层的末尾,将最后一个节点的next
设置为null
。
复杂度
-
时间复杂度:O(n),其中n是二叉树中的节点数。每个节点恰好被访问一次。
-
空间复杂度:O(n),在最坏的情况下,队列中存储了所有节点。对于一个完美二叉树,队列最多存储当前层的所有节点,即树的一半节点。
Code
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
if (root == null) return null;
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
Node leftMost = root;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Node current = queue.poll();
if (i > 0) {
leftMost.next = current;
}
leftMost = current;
if (current.left != null) {
queue.offer(current.left);
}
if (current.right != null) {
queue.offer(current.right);
}
}
leftMost.next = null;
}
return root;
}
}