【LeetCode 二叉树专项】二叉树展开为链表(114)

1. 题目

给定一棵二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null
  • 展开后的单链表应该与二叉树 前序遍历 顺序相同。

1.1 示例

  • 示例 1 1 1
  • 输入: root = [1, 2, 5, 3, 4, null, 6]
  • 输出: [1, null, 2, null, 3, null, 4, null, 5, null, 6]

在这里插入图片描述

  • 示例 2 2 2
  • 输入: root = []
  • 输出: []
  • 示例 3 3 3
  • 输入: root = [0]
  • 输出: [0]

1.2 说明

1.3 限制

  • 树中结点数在范围 [ 0 ,   2000 ] [0,\textit{ }2000] [0, 2000] 内;
  • -100 <= Node.val <= 100

1.4 进阶

你可以使用原地算法( O ( 1 ) O(1) O(1) 额外空间)展开这棵树吗?

2. 解法一(前序遍历)

2.1 分析

本题的题干提示的非常明确,即展开后的单链表应该与二叉树 前序遍历 顺序相同,故最简单的方式就是先通过前序遍历得到所有结点的 val 值,然后再依次使用 TreeNode 创建结点并连接成单链表。

2.2 解答

from json import dumps
from typing import List


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    def _flatten(self, root: TreeNode, tree: List[int]):
        if not root:
            return
        tree.append(root.val)
        self._flatten(root.left, tree)
        self._flatten(root.right, tree)

    def flatten(self, root: TreeNode) -> None:
        tree = []
        self._flatten(root, tree)
        if not root:
            return
        size = len(tree)
        node = root
        root.left = None
        for i in range(1, size):
            node.right = TreeNode(tree[i])
            node = node.right


def main():
    node6 = TreeNode(6)
    node5 = TreeNode(4)
    node4 = TreeNode(3)
    node3 = TreeNode(5, left=None, right=node6)
    node2 = TreeNode(2, left=node4, right=node5)
    node1 = TreeNode(1, left=node2, right=node3)
    root = node1
    sln = Solution()
    sln.flatten(root)
    tree = []

    def preorder_traverse(flattened_root: TreeNode):
        if not flattened_root:
            tree.append(None)
            return
        tree.append(flattened_root.val)
        preorder_traverse(flattened_root.left)
        preorder_traverse(flattened_root.right)

    preorder_traverse(root)
    print(dumps(tree))  # [1, null, 2, null, 3, null, 4, null, 5, null, 6, null, null]


if __name__ == '__main__':
    main()

实际上,我们并不需要在前序遍历之后再重新创建结点,而是可以在前序遍历时就将结点保存起来而非保存结点的 val 值:

from json import dumps
from typing import List


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    def _flatten(self, root: TreeNode, tree: List[TreeNode]):
        if not root:
            return
        tree.append(root)
        self._flatten(root.left, tree)
        self._flatten(root.right, tree)

    def flatten(self, root: TreeNode) -> None:
        tree = []
        self._flatten(root, tree)
        if not root:
            return
        size = len(tree)
        node = root
        for i in range(1, size):
            node.right = tree[i]
            node.left = None
            node = node.right

2.3 复杂度

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/121118451