题目描述:
根据一棵树的前序遍历与中序遍历构造二叉树。(假设树中没有重复元素)
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
算法思想:
前序遍历是“根左右”,中序遍历是“左根右”,我们先举例看一下内部关系
m代表根节点,l代表根节点的左子树,r代表根节点的右子树。
不难发现,根节点的左子树和根节点的右子树它们分别又是同样的处理流程,也就是说,可以使用同样的函数递归处理。
先给出代码:
public TreeNode buildTree(int[] preorder, int[] inorder) {
return build(inorder, 0, inorder.length-1, preorder, 0, preorder.length-1);
}
public TreeNode build(int[] inorder, int inStart, int inEnd, int[] preorder, int preStart, int preEnd) {
//终止条件
if(inStart > inEnd || preStart > preEnd) return null;
//根操作
int rootVal = preorder[preStart];
TreeNode root = new TreeNode(rootVal);
//找到中序中根的位置
int mid = inStart;
for(int i = inStart + 1; i <= inEnd; ++i) {
if(inorder[i] == rootVal) {
mid = i;
break;
}
}
int leftSize = mid - inStart; //左子树的数据个数,用于定位
//建立左子树
root.left = build(inorder, inStart, mid - 1, preorder, preStart + 1, preStart + leftSize);
//建立右子树
root.right = build(inorder, mid + 1, inEnd, preorder, preStart + leftSize + 1, preEnd);
return root;
}
这里的处理难点在于准确找到左右子树的递归入口,注意不要陷入具体的细节,而是力求找到与原问题同样的子问题。
同样的,从后序和中序也能构造二叉树,只是更改入口参数而已,可见力扣106题。