Skip to main content

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

Tips

题目类型: Tree

题目

给定一个完美二叉树, 其所有叶子节点都在同一层, 每个父节点都有两个子节点. 二叉树定义如下:

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

填充它的每个 next 指针, 让这个指针指向其下一个右侧节点. 如果找不到下一个右侧节点, 则将 next 指针设置为 NULL 初始状态下, 所有 next 指针都被设置为 NULL.

进阶:

你只能使用常量级额外空间.

使用递归解题也符合要求, 本题中递归程序占用的栈空间不算做额外的空间复杂度.

示例

输入:

     1
/ \
2 3
/ \ / \
4 5 6 7

输出:

     1 -> null
/ \
2 -> 3 -> null
/ \ / \
4 ->5->6-> 7 -> null

题解

一棵树中存在两种 next 类型(下面以 node 为 2 那个节点说明):

某个 node 节点的左子节点和左子节点连接, 如 4, 5 两个节点, 它们其实是 2 的子节点, 如果连接的话, 即 node.left.next = node.right

116-connect-1

某个 node 节点的右子节点和另一个 node 节点的左子节点连接, 如 5, 6 两个节点. 对于这种情况, 可以和上面结合起来一起看, 5 实际就是 node.right, 而 6 实际就是 node.next.left (注: node.next 是 3), 如果连接的话, 即 node.right.next = node.next.left

116-connect-2

时间复杂度和空间复杂度均为 O(n)

var connect = function (root) {
if (root === null) {
return root
}

// 从根节点开始
let leftmost = root

while (leftmost.left !== null) {
// 遍历这一层节点组织成的链表, 为下一层的节点更新 next 指针
let head = leftmost

while (head !== null) {
// CONNECTION 1: 某个节点的直接左右子节点连接
head.left.next = head.right

// CONNECTION 2: 某个节点的右子节点和另一个节点的左子节点连接
if (head.next !== null) {
head.right.next = head.next.left
}

// 指针向后移动
head = head.next
}

// 去下一层的最左的节点
leftmost = leftmost.left
}

return root
}

时间复杂度: O(N), 每个节点只访问一次

空间复杂度: O(1), 不需要存储额外的节点