日野弥生:勉強しよう

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

发表于2025年02月22日

#树 #二叉树 #广度优先搜索 #深度优先搜索 #链表

本题由于next指针的前后关系,很容易想到使用广度优先搜索的思路进行层次遍历。但是层次遍历会随着二叉树深度的增加而指数增长,不符合题干要求。

转换思路,考虑先序遍历。先把根节点的左子树的next指针连向右子树。同时记录右子树的结点进入字典中。这里考虑用字典是键值可以存储树高,从而保证进入字典中的诸层级的右节点的next指针都能连接到同一层级的结点。

同时,从字典中查找和层级数相同的key是否存在,如果存在就从字典中删除该项并把该项的next连向left结点。

值得一提的是,用字典的好处不仅在于上述原因,还在于字典同一层级的键值对确实只有一个,毕竟如果从字典删除后马上就会把left的right送进字典。

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

def create_perfect_binary_tree(nums):
    """
    创建一个包含给定数字的完美二叉树。

    Args:
        nums: 一个包含二叉树节点值的列表。

    Returns:
        完美二叉树的根节点。
    """

    if not nums:
        return None

    # 计算树的深度
    depth = 0
    num_nodes = len(nums)
    while (1 << (depth + 1)) - 1 < num_nodes:
        depth += 1

    def build_tree(index, level):
        """
        递归构建二叉树。

        Args:
            index: 当前节点在列表 nums 中的索引。
            level: 当前节点的深度。

        Returns:
            当前节点。
        """

        if level > depth or index >= num_nodes:
            return None

        node = Node(nums[index])

        node.left = build_tree(2 * index + 1, level + 1)
        node.right = build_tree(2 * index + 2, level + 1)

        return node

    return build_tree(0, 0)

# 测试代码
nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
root = create_perfect_binary_tree(nums)

# 验证二叉树是否创建成功(可选)
def print_tree(node):
    if node:
        print(node.val)
        if node.next:
                print(node.val, node.next.val, sep="->")
        print_tree(node.left)
        print_tree(node.right)

class Solution:
    # 字典存储结点和深度的键值对
    q = {}
    def connectIMPL(self, root: 'Optional[Node]', depth: int) -> 'Optional[Node]':
        if root is None:
            return None
        # 由于是完美二叉树,所以左右子树要么同时没有,要么同时存在
        if root.left and root.right:
            # 左子节点的next指向右子结点
            root.left.next = root.right
            # 如果字典中有符合的结点,则连向左结点
            if self.q:
                item = self.q.get(depth+1)
                if item:
                    lastRight = self.q.pop(depth + 1)
                    lastRight.next = root.left
            # 继续往字典送进同级的右子节点
            self.q[depth+1]=root.right
        # 递归
        self.connectIMPL(root.left, depth + 1)
        self.connectIMPL(root.right, depth + 1)
        return root
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        return self.connectIMPL(root, 0)

s = Solution()
s.connect(root)
print_tree(root)

フラッシュタブ:LeetCode

题目链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/

上一篇

LeetCode 105 - 从前序与中序遍历序列构造二叉树

下一篇

LeetCode 117 - 填充每个节点的下一个右侧节点指针 II