【LeetCode 二叉树专项】从中序与后序遍历序列构造二叉树(106)

1. 题目

定一棵树的中序遍历 inorder 与后序遍历 postorder 序列。请构造二叉树并返回其根节点。

1.1 示例

  • 示例 1 1 1
    在这里插入图片描述
  • 输入: inorder = [9, 3, 15, 20, 7]postorder = [9, 15, 7, 20, 3]
  • 输出: [3, 9, 20, null, null, 15, 7]
  • 示例 2 2 2
  • 输入: inorder = [-1]postorder = [-1]
  • 输出: [-1]

1.2 说明

1.3 限制

  • 1 <= preorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorderpostorder 均无重复元素;
  • inorder 均出现在 postorder
  • inorder 保证为二叉树的中序遍历序列;
  • postorder 保证为二叉树的后序遍历序列。

2. 解法一(递归)

2.1 分析

此题和【LeetCode 二叉树专项】从前序与中序遍历序列构造二叉树(105)十分类似,解答的方法也相近。下面仅给出三张示意图:

  • 如何通过 postorder 序列找到根节点对应 val 域及其在 inorder 序列中的索引;
  • 如何通过根节点在 inorder 序列中的索引递归构建根节点的左子节点;
  • 如何通过根节点在 inorder 序列中的索引递归构建根节点的右子节点。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.2 实现

from collections import deque
from typing import List, Optional


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


class Solution:
    def _build_tree(self, inorder: List[int], in_start: int, in_stop: int,
                    postorder: List[int], post_start: int, post_stop) -> Optional[TreeNode]:
        if in_start > in_stop or post_start > post_stop:
            return
        index = inorder.index(postorder[post_stop])
        root = TreeNode(postorder[post_stop])
        root.left = self._build_tree(inorder, in_start, index - 1,
                                     postorder, post_start, post_start + index - 1 - in_start)
        root.right = self._build_tree(inorder, index + 1, in_stop,
                                      postorder, post_stop - in_stop + index, post_stop - 1)
        return root

    def build_tree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        return self._build_tree(inorder, 0, len(inorder) - 1, postorder, 0, len(inorder) - 1)


def main():
    inorder = [5, 2, 6, 4, 7, 1, 8, 3, 9]
    postorder = [5, 6, 7, 4, 2, 8, 9, 3, 1]
    sln = Solution()
    root = sln.build_tree(inorder, postorder)

    tree = []
    visiting = deque([root])
    while visiting:
        node = visiting.popleft()
        if node:
            tree.append(node.val)
            visiting.append(node.left)
            visiting.append(node.right)
        else:
            tree.append(None)

    while True:
        if not tree[-1]:
            tree.pop()
        else:
            break

    print(tree)  # [1, 2, 3, 5, 4, 8, 9, None, None, 6, 7]


if __name__ == '__main__':
    main()

2.3 复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是树中的节点个数;
  • 空间复杂度: O ( n ) O(n) O(n)。我们需要使用 O ( n ) O(n) O(n) 的空间存储哈希表,以及 O ( h ) O(h) O(h)(其中 h h h 是树的高度)的空间表示递归时栈空间。这里 h < n h < n h<n,所以总空间复杂度为 O ( n ) O(n) O(n)

3. 解法二(迭代)

作者: LeetCode-Solution

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值