def buildTree_v2(preorder, inorder):
    if inorder:
        ind = inorder.index(preorder.pop(0))
        root = TreeNode(inorder[ind])
        root.left = buildTree(preorder, inorder[0:ind])
        root.right = buildTree(preorder, inorder[ind+1:])
        return root
def build(inorder, postorder, inStart, inEnd, postStart, postEnd):

    # print(inStart, inEnd, postStart, postEnd)

    if inEnd - inStart == 0:
        return None

    if inEnd - inStart == 1:
        return TreeNode(postorder[postStart])

    root = TreeNode(postorder[postEnd - 1])

    left_in_set = set()
    pointer = inStart
    while inorder[pointer] != root.val:
        left_in_set.add(inorder[pointer])
        pointer += 1
    leftInEnd = pointer
    rightInStart = pointer + 1

    pointer = postStart
    while postorder[pointer] in left_in_set:
        pointer += 1
    leftPosEnd = pointer
    rightPosStart = pointer

    root.left = build(inorder, postorder, inStart, leftInEnd, postStart, leftPosEnd)
    root.right = build(inorder, postorder, rightInStart, inEnd, rightPosStart, postEnd - 1)

    return root
def recursive(startN, endN, d):
    """
    :param startN:
    :param endN:
    :param result:
    :return:
    """

    if (startN, endN) in d:
        return d[(startN, endN)]

    if endN - startN < 0:
        d[(startN, endN)] = [None]
        return d[(startN, endN)]

    if endN - startN == 0:
        d[(startN, endN)] = [TreeNode(startN)]
        return d[(startN, endN)]

    ans = []
    for i in range(startN, endN + 1):
        ansL = recursive(startN, i - 1, d)
        ansR = recursive(i + 1, endN, d)

        for nl in ansL:
            for nr in ansR:
                node = TreeNode(i)
                node.left = nl
                node.right = nr
                ans.append(node)

    return ans
def buildTree(inorder, postorder):

    if inorder:
        ind = inorder.index(postorder.pop())
        root = TreeNode(inorder[ind])
        root.right = buildTree(inorder[ind+1:], postorder)
        root.left = buildTree(inorder[:ind], postorder)
        return root

    return None
def sortedArrayToBST(nums):

    if len(nums) == 0:
        return None
    if len(nums) == 1:
        return TreeNode(nums[0])

    mid = len(nums) // 2
    root = TreeNode(nums[mid])
    root.left = sortedArrayToBST(nums[0:mid])
    root.right = sortedArrayToBST(nums[mid + 1 :])
    return root
def buildTree(preorder, inorder):

    """
    :param preorder:
    :param inorder:
    :return:
    """

    if len(preorder) != len(inorder):
        raise Exception('len(preorder) != len(inorder)')

    if not preorder:
        return None

    if len(preorder) == 1:
        return TreeNode(preorder[0])

    root = TreeNode(preorder[0])

    left_pre = []
    left_in = []

    right_pre = []
    right_in = []

    pointer = 0
    while inorder[pointer] != root.val:
        left_in.append(inorder[pointer])
        pointer += 1

    pointer += 1
    while pointer < len(inorder):
        right_in.append(inorder[pointer])
        pointer += 1

    left_set = set(left_in)
    pointer = 1
    while pointer < len(preorder):
        e = preorder[pointer]
        pointer += 1
        if e in left_set:
            left_pre.append(e)
        else:
            right_pre.append(e)

    root.left = buildTree(left_pre, left_in)
    root.right = buildTree(right_pre, right_in)

    return root