这两道题是相关系的。
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。
I 和 II 的区别在于给定的二叉树是否是完美二叉树还是任意二叉树。
如果是满二叉树,我们可以在当前层就为下一层的next连接好。但如果是任意二叉树,需要设置一个哨兵节点,挺巧妙的。
针对满二叉树的情况
如果要4和5连接,父节点2是直接可以访问到这两个节点的。 如果要5和6连接,我们可以通过访问父节点的next的left实现。
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return None
if root.left:
root.left.next = root.right
if root.right:
root.right.next = None if not root.next else root.next.left
self.connect(root.left)
self.connect(root.right)
return root
针对任意二叉树
我们没法直接利用父子节点关系连接子节点的next指针,因为有些同层的节点是None。
首先按照层次遍历的思想(只用一个指针实现层次遍历,因为有了next,不需要其他数据结构)
假设当前层已经完成好了next指针的建立,为每一层都设置一个头指针,指向最左边的元素(tail),然后curr(父节点)已经建立的next节点,可以把tail用next把同一层的节点串起来。
class Solution:
def connect(self, root: 'Node') -> 'Node':
curr = root
dummpy = Node(-1) # 哨兵节点
while curr:
tail = dummpy # 初始化tail
while curr: # 层次遍历
if curr.left: # 把下一层用tail串起来
tail.next = curr.left
tail = tail.next
if curr.right:
tail.next = curr.right
tail = tail.next
curr = curr.next # 直接跳到同一层的下一个节点上
curr = dummpy.next # 哨兵节点的next一定是下一层的最左边的节点
if dummpy is tail: # 终止条件 如果没有会死循环 当下一层没有节点的时候终止
break
return root