将 N 叉树编码为二叉树

Submission

运行时间: 46 ms

内存: 17.4 MB

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children if children is not None else []

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
"""

class Codec:
    # Encodes an n-ary tree to a binary tree.
    def encode(self, root: 'Optional[Node]') -> Optional[TreeNode]:
        if root is None:
            return None
        
        binary_root = TreeNode(root.val)
        if root.children:
            binary_root.left = self.encode_children(root.children)
        
        return binary_root
    
    def encode_children(self, children):
        if not children:
            return None
        
        first_child = children[0]
        binary_node = TreeNode(first_child.val)
        binary_node.left = self.encode_children(first_child.children)
        binary_node.right = self.encode_children(children[1:])
        
        return binary_node
    
    # Decodes your binary tree to an n-ary tree.
    def decode(self, data: Optional[TreeNode]) -> 'Optional[Node]':
        if data is None:
            return None
        
        n_ary_root = Node(data.val)
        n_ary_root.children = self.decode_children(data.left)
        
        return n_ary_root
    
    def decode_children(self, node):
        if node is None:
            return []
        
        n_ary_child = Node(node.val)
        n_ary_child.children = self.decode_children(node.left)
        siblings = self.decode_children(node.right)
        return [n_ary_child] + siblings

Explain

这个题解通过将N叉树(N-ary Tree)编码为二叉树(Binary Tree)的方式解决了如何在二叉树的数据结构中表示一个N叉树的问题。编码过程中,每个N叉树节点的所有子节点被转换为二叉树中的左子树,其中每个子节点成为前一个子节点的右子节点。解码过程则是编码的逆过程,它通过遍历二叉树,重新构建出原始的N叉树结构。

时间复杂度: O(n)

空间复杂度: O(n)

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children if children is not None else []

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
"""

class Codec:
    # Encodes an n-ary tree to a binary tree.
    def encode(self, root: 'Optional[Node]') -> Optional[TreeNode]:
        if root is None:
            return None
        
        binary_root = TreeNode(root.val) # 创建二叉树的根节点
        if root.children:
            binary_root.left = self.encode_children(root.children) # 将N叉树的所有子节点编码为二叉树的左子树
        
        return binary_root
    
    def encode_children(self, children):
        if not children:
            return None
        
        first_child = children[0]
        binary_node = TreeNode(first_child.val) # 第一个子节点成为二叉树的根节点
        binary_node.left = self.encode_children(first_child.children) # 递归地编码子节点的子树
        binary_node.right = self.encode_children(children[1:]) # 将其他子节点作为右子树
        
        return binary_node
    
    # Decodes your binary tree to an n-ary tree.
    def decode(self, data: Optional[TreeNode]) -> 'Optional[Node]':
        if data is None:
            return None
        
        n_ary_root = Node(data.val) # 创建N叉树的根节点
        n_ary_root.children = self.decode_children(data.left) # 解码二叉树的左子树以获取所有子节点
        
        return n_ary_root
    
    def decode_children(self, node):
        if node is None:
            return []
        
        n_ary_child = Node(node.val) # 创建子节点
        n_ary_child.children = self.decode_children(node.left) # 递归解码所有子节点
        siblings = self.decode_children(node.right) # 解码右子树以获取兄弟节点
        return [n_ary_child] + siblings
"""

Explore

在编码N叉树到二叉树的过程中,选择第一个子节点作为二叉树的左子节点是为了保持子节点的顺序和层次结构。将第一个子节点作为左子节点后,可以利用二叉树的右子节点表示N叉树中同一父节点的其余子节点。这种方法使得每一个N叉树节点的子节点列表可以通过二叉树的左子节点和右子节点链式地表示出来,从而实现N叉树到二叉树的转换。

在解码过程中,通过递归地访问二叉树的左子节点来恢复N叉树节点的子节点,并通过右子节点递归地恢复同一父节点下的其他子节点。这种顺序访问确保了原始N叉树中子节点的顺序被完整地保持。首先解码作为左子节点的第一个子节点,然后递归地解码右子节点链中的其他节点,这样可以确保所有子节点按照原始的顺序和层级关系被正确恢复。

在`encode_children`方法中,使用`children[1:]`进行切片操作,这会创建当前子节点列表的一个新副本,除了第一个元素外包含所有子节点。这种切片操作的空间复杂度为O(n),其中n是子节点的数量,因为它需要额外的空间来存储副本。虽然这增加了空间复杂度,但通常不会对算法的整体性能产生显著影响,除非子节点的数量非常大。在实际应用中,可以通过优化代码结构,比如使用迭代器或索引,来减少不必要的空间使用,提高性能。