116.填充每个节点的下一个右侧节点指针
描述
中等
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
实例
输入:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{"$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{"$id":"5","left":{"$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{"$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1}
输出:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":{"$id":"4","left":null,"next":{"$id":"5","left":null,"next":{"$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{"$id":"7","left":{"$ref":"5"},"next":null,"right":{"$ref":"6"},"val":3},"right":{"$ref":"4"},"val":2},"next":null,"right":{"$ref":"7"},"val":1}
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。
提示
- 你只能使用常量级额外空间。
- 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度
解题
这个好像直接用层次遍历就能解决
一层一层地添加节点,如果不是该层的最后一个节点,直接用next指针连接起来
一层随后一个节点不用处理,因为它本身的next指针就是空的
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return root
queue = []
queue.append(root)
while queue:
# 一层的节点数
size = len(queue)
for i in range(size):
# 取出第一个节点
node = queue.pop(0)
# 除最后一个节点外,其余节点间添加链接
if i < size - 1:
node.next = queue[0]
# 添加下一层的节点
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
不过层次遍历使用的不是常量级的额外空间,不符合题目要求
已知完美二叉树的非叶节点都具有左右两孩子
递归,代码应该很清楚,画个图就明白了
class Solution:
def connect(self, root: 'Node') -> 'Node':
# 忽略空节点和叶子节点
if not root or not root.left:
return root
# 添加子节点之间的连接
root.left.next = root.right
# 如果存在next,添加左边节点的右孩子和右边节点的左孩子之间的连接
if root.next:
root.right.next = root.next.left
self.connect(root.left)
self.connect(root.right)
return root
非递归 , 一层一层地添加链接
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return
R = root
while root.left: # 存在下一层
next_layer = root.left # 下一层的第一个节点
while root.next: # 当root为第一层的根节点时,没有next指针,不执行
root.left.next = root.right
root.right.next = root.next.left
root = root.next
root.left.next = root.right
root = next_layer
return R
117.填充每个节点的下一个右侧节点指针ii
描述
中等
和116一样,也是添加next指针,不过这次不是完美二叉树
解题
当不是完美二叉树时,层序遍历仍然可以AC
递归版本
定义了一个找右侧下一个节点的函数
需要先递归右子树,否则不能正确建立右侧的next
class Solution:
def connect(self, root: 'Node') -> 'Node':
# 忽略空节点和叶子节点
if not root or (not root.left and not root.right):
return root
# 如果左右子节点都存在
if root.left and root.right:
root.left.next = root.right
root.right.next = self.get_next(root)
# 如果仅存在右子节点
elif root.right:
root.right.next = self.get_next(root)
# 如果仅存在左子节点
else:
root.left.next = self.get_next(root)
self.connect(root.right)
self.connect(root.left)
return root
# 一直向右找到节点,返回的root的其中一个子节点或空
# root的子节点所在的层才是目标节点所在的层
def get_next(self, root):
while root.next:
# 如果存在左节点
if root.next.left:
return root.next.left
# 如果存在右节点
elif root.next.right:
return root.next.right
root = root.next
# 如果不存在目标节点,返回空
return None