剑指Offer编程题-重建二叉树

题目:重建二叉树

题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路

以先序{1,2,4,7,3,5,6,8}和中序{4,7,2,1,5,3,8,6}为例:先序遍历的顺序是根结点->左子树->右子树,那么对于每一个先序序列,序列的第一个数必然是这个树的根节点,此时根节点为1;中序遍历的顺序是左子树->根节点->右子树,那么对于每一个中序序列,其序列可被根节点划分为左右两部分,比如此时我们已经由先序序列得知1是根结点,在中序序列中,{4,7,2}{5,3,8,6}是被根节点1划分的两个部分,且分别对应于整棵树的左子树和右子树。将左子树和右子树分别看作两棵完整的树,使用递归继续划分就可重建出整棵二叉树。

实现

python

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if len(pre) > 0:
            node = TreeNode(pre[0])
            # 根节点在中序序列中的位置
            index = tin.index(pre[0])
            if len(pre[1:index+1])>0:
                node.left = self.reConstructBinaryTree(pre[1:index+1], tin[0:index])
            if len(pre[index+1:])>0:
                node.right = self.reConstructBinaryTree(pre[index+1:], tin[index+1:])
            return node
        else:
            return None

讨论区大神的简洁版(每一次处理左子树时都将节点pop掉):

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if not pre or not tin:
            return None
        root = TreeNode(pre.pop(0))
        index = tin.index(root.val)
        root.left = self.reConstructBinaryTree(pre, tin[:index])
        root.right = self.reConstructBinaryTree(pre, tin[index + 1:])
        return root

补充内容

二叉树的遍历方式:

  • 先序遍历:根节点->左子树->右子树

  • 中序遍历:左子树->根节点->右子树

  • 后序遍历:左子树->右子树->根节点

代码实现(上文题目的验证过程):

# -*- coding:utf-8 -*-
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        node = None
        if len(pre) > 0:
            node = TreeNode(pre[0])
            index = tin.index(pre[0])
            pre_l = pre[1:index+1]
            pre_r = pre[index+1:]
            tin_l = tin[0:index]
            tin_r = tin[index+1:]
            if len(pre_l)>0:
                node.left = self.reConstructBinaryTree(pre_l, tin_l)
            if len(pre_r)>0:
                node.right = self.reConstructBinaryTree(pre_r, tin_r)
        return node


# 先序遍历
def preorderTraversal(node):
    if node != None:
        print(node.val)
    if node.left != None:
        preorderTraversal(node.left)
    if node.right != None:
        preorderTraversal(node.right)


# 中序遍历
def inorderTraversal(node):
    if node.left != None:
        inorderTraversal(node.left)
    if node != None:
        print(node.val)
    if node.right != None:
        inorderTraversal(node.right)


# 后序遍历
def postorderTraversal(node):
    if node.left != None:
        postorderTraversal(node.left)
    if node.right != None:
        postorderTraversal(node.right)
    if node != None:
        print(node.val)


pre = [1,2,4,7,3,5,6,8]
tin = [4,7,2,1,5,3,8,6]
node = Solution().reConstructBinaryTree(pre, tin)
print('pre:')
preorderTraversal(node)
print('in:')
inorderTraversal(node)
print('post:')
postorderTraversal(node)