题目:输入某二叉树的前序遍历和中序遍历的结构,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出下图所示的二叉树并输出它的头结点。
思路:在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在中序遍历序列中,根节点的值在序列的中间,左子树的节点的值位于根节点的值的左边,而右子树的节点的值位于根节点的值的右边。
辅助函数:判断异常情况,例如序列为空,不等长等。
功能函数:构建二叉树。
- pre的pres的节点记为root节点,在in中找到root节点的位置,根据root在in的片段中所处的位置,判断是否有左子树或者右子树。
- 如果存在子树,以左子树为例。根据左子树的长度,在pre中分割出左子树的片段,将片段中第一个值设置为root,进行新一轮的递归。
- 递归结束:没有左子树或者右子树。
难点:存在子树时,切割片段中pres,ins,pree,ine的设定。
Java题解
// 筛选空数列,数列不等长等异常情况
public TreeNode constructTree(int[] pre, int[] in) {
if (pre.length==0 || in.length==0 || pre.length!=in.length)
return null;
return helpconstructTree(pre, in, 0, pre.length-1, 0, in.length-1);
}
// 构建二叉树主函数
public TreeNode helpconstructTree(int[] pre, int[] in, int pres, int pree, int ins, int ine) {
TreeNode root = new TreeNode(pre[pres]);
int rootloc = findRoot(in, pre[pres], ins, ine);
if (rootloc > ins) { // 有左子树
int lpree = pres + (rootloc - ins);
root.left = helpconstructTree(pre, in, pres+1, lpree, ins, rootloc-1);
}
if (rootloc < ine) { // 有右子树
int rpres = pres + (rootloc - ins) + 1;
root.right = helpconstructTree(pre, in, rpres, pree, rootloc+1, ine);
}
return root;
}
// 找到pre第一个(root)在in的位置
public int findRoot(int[] nums, int num, int s, int e) {
int i = s;
for (; i <= e; i++) {
if (nums[i] == num)
return i;
}
return -1;
}
Python题解
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if len(preorder)==0 or len(inorder)==0:
return None
if len(preorder)==1 or len(inorder)==1:
return TreeNode(preorder[0])
for i in range(len(inorder)):
if inorder[i] == preorder[0]:
break
root = TreeNode(preorder[0])
root.left = self.buildTree(preorder[1:1+i], inorder[:1+i])
root.right = self.buildTree(preorder[1+i:], inorder[1+i:])
return root