二叉树的中序/前序/后序遍历

'''
首先,preorder 中的第一个元素一定是树的根,这个根又将 inorder 序列分成了左右两棵子树。
现在我们只需要将先序遍历的数组中删除根元素,然后重复上面的过程处理左右两棵子树。

递归+二分:
特点:速度快, 为什么转成哈希表:为了更快的搜索速度
时间复杂度 O(n)
空间复杂度O(n)
'''
from typing import List

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

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder)==0 or len(inorder)==0 or len(preorder)!=len(inorder):
            return None
        pre_idx = 0
        idx_map = {val:idx for idx,val in enumerate(inorder)}
        def helper(left_inorder=0 , right_inorder = len(inorder)-1):
            nonlocal pre_idx
            if left_inorder > right_inorder:
                return None
            root = TreeNode(preorder[pre_idx])
            index = idx_map[preorder[pre_idx]]
            pre_idx += 1
            root.left = helper(left_inorder, index-1)
            root.right = helper(index+1 , right_inorder)
            return root
        return helper()
        

'''
扩展:
题目描述
给定一颗二叉树,二叉树每个节点都有唯一的正整数值代表节点,在遍历时,我们使用节点的数值作为标记。
给定二叉树的前序和中序遍历结果,求二叉树的叶子节点个数。
输入
第一行,输入二叉树节点个数N,其中0 < N < 30000
第二行与第三行,分别输入二叉树的前序和中序遍历结果,每个节点对应唯一整数值
输出
二叉树叶子节点个数
样例输入
3
1 3 4
3 1 4
样例输出
2
'''
#中序+前序
def dfs_pre_mid(pl, pr, ml, mr, val2id):
    global ans
    # pl 位置对应的是根结点
    if pl == pr: # ml==mr应该也可以
        ans += 1
        return
    # 找到根结点在 中序遍历中的位置,左边是左子树,右边是右子树
    idx = val2id[pre[pl]]
    left_len = idx - ml
    # right_len = mr - idx
    # 左子树, 每一轮递归把pl,idx去掉
    dfs_pre_mid(pl+1, pl+left_len, ml, idx-1, val2id)
    # 右子树
    dfs_pre_mid(pl+left_len+1, pr, idx+1, mr, val2id)

#中序+后序
def dfs_lst_mid(ll, lr, ml, mr, val2id):
    global ans
    # lr 位置对应的是根结点
    if ll == lr:
        ans += 1
        return
    idx = val2id[last[lr]]
    right = mr - idx
    # 右子树
    dfs_lst_mid(lr-right, lr-1, idx+1, mr, val2id)
    # 左子树
    dfs_lst_mid(ll, lr-right-1, ml, idx-1, val2id)

if __name__ == '__main__':
    n = int(input().strip())
    # pre = list(map(int, input().strip().split()))
    mid = list(map(int, input().strip().split()))
    last = list(map(int, input().strip().split()))

    lenth = len(mid)
    ans = 0
    val2id = {val: id for id,val in enumerate(mid)}
    # dfs_pre_mid(0, lenth-1, 0, lenth-1, val2id)
    dfs_lst_mid(0, lenth - 1, 0, lenth - 1, val2id)
    print(ans)


# n = 15
# pre: 1 2 4 8 9 5 10 11 3 6 12 13 7 14 15
# in: 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15
# post: 8 9 4 10 11 5 2 12 13 6 14 15 7 3 1
# 叶子结点个数:8
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值