一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。
一、题目
leetcode 填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
示例 1:
输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。
示例 2:
输入:root = []
输出:[]
提示:
树中节点的数量在 [0, 212 - 1] 范围内
-1000 <= node.val <= 1000
二、题解
简单来说就是需要将一个完全二叉树的每一层节点从左到右连接成一个单链表。
方法一
既然是要将二叉树的每一层节点连接成链表,那么我们就可以获取到二叉树的每一层节点,然后顺序连接成一个链表就可以了。具体的要获取二叉树每一层的链表我们可以对二叉树节点进行层序遍历,我们要按层遍历二叉树可以使用一个队列来辅助,这样可以比较方便的获取层元素节点。首先将根节点加入队列,然后记录下当前队列的元素数量size代表当前层的节点数量,然后我们就将队列的size个元素取出,然后就取出的元素节点连接到队列的下一个元素,除非当前元素是最后一个元素,那就不用连接了,最后为了下一层遍历,我们需要将当前元素节点的子树添加到队列中。最后就需要循环取出队列元素,直到队列不存在元素为止,然后返回root即可。
方法二
首先对于初始的根节点,我们不需要连接,对于根节点下的子节点我们只需将左节点连接上右节点即可。而对于子树的根节点,其会连接上其他子树的根节点,所以还需要将两个子树的子节点也要连接。所以我们可以递归的处理连接,具体的如果当前节点为空就是不需要处理的,否则当前节点的左节点不为空的话就将左节点的next连接上右节点即可;同时如果根节点的next有连接,那么还需要将右节点的next连接上根节点的next下的左节点。最后再递归的去处理左子树和右子树。
三、代码
方法一 Java代码
class Solution {
public Node connect(Node root) {
if (root == null) {
return null;
}
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Node node = queue.poll();
if (node == null) {
continue;
}
if (i != size - 1) {
node.next = queue.peek();
}
queue.add(node.left);
queue.add(node.right);
}
}
return root;
}
}
时间复杂度:O(n),需要遍历二叉树所有节点。
空间复杂度:O(n),需要一个队列空间辅助遍历层元素。
方法二 Java代码
class Solution {
public Node connect(Node root) {
if (root == null) {
return null;
}
if (root.left != null) {
root.left.next = root.right;
if (root.next != null) {
root.right.next = root.next.left;
}
}
connect(root.left);
connect(root.right);
return root;
}
}
时间复杂度:O(n),需要遍历二叉树所有节点。
空间复杂度:O(1)。