输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
前序遍历:先根节点,然后左节点,然后右节点
中序遍历:先左节点,然后根节点,然后右节点
后序遍历:先左节点,然后右节点,然后根节点
采用递归的方法
通过前序得到根节点
在中序中找到前序对应位置,前序左侧的就是左子树,前序右侧的就是右子树
这样递归得到左右子树,并逐渐建立整棵树
时间复杂度 找根节点在中序中位置是O(n),递归应该是O(logn),所以整体应该是O(nlogn)
public class Solution {
//题目入口函数
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre == null || in == null || pre.length == 0 || in.length== 0){
//因参数导致的无效
return null;
}
return buildTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
}
//建树函数
public TreeNode buildTree(int [] pre, int preStart, int preEnd, int [] in, int inStart, int inEnd){
if(preStart > preEnd || inStart > inEnd){
//递归调用,可能递归至叶节点下的空指针处,返回null即可
return null;
}
//创建根节点,前序第一个即是
TreeNode root = new TreeNode(pre[preStart]);
int index = inStart;
//找到根节点在中序中的位置
while(in[index] != pre[preStart]){
index++;
}
//左子树长度
int leftLength = index - inStart;
//右子树长度
int rightLength = inEnd - index;
//pre切割为 preStart 左子树长度一段 右子树长度一段(结尾为preEnd)
//in切割为 左子树长度一段 index 右子树长度一段(结尾为inEnd)
root.left = buildTree(pre, preStart + 1, preStart + leftLength, in, inStart, index - 1);
root.right = buildTree(pre, preStart + leftLength + 1, preEnd, in, index + 1, inEnd);
//返回构建好的子树
return root;
}
}
网友评论