题目来源
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7
限制:
0 <= 节点个数 <= 5000
思路:最开始的想法是建一个栈,然后依次入栈,根据某些条件把叶子节点出栈,跑起来用例只过了一半多,因为将叶子节点出栈的时候不知道到底跑几层循环。所有想到了用递归,这道题的关键就是把两个数组的同一部分对应
对于前序遍历的某个节点来说,有这样的规律:根节点 | 左子树 | 右子树
对于中序遍历的某个节点来说,有这样的规律:左子树 | 根节点 | 右子树
所以重点就是将相同的段对应起来,每次进入递归函数的前序起始点就是这次递归里的根节点,然后分别让另外的两段对应起来进行下次递归即可。想法很美好。。就是结果不尽如人意,太慢了。先这样,以后有好的想法再说。
//存中序数组的下标,后面对应的时候要用,刚开始用一个for循环,太慢了, 改成这个,还是很慢
private static HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
public static void init(HashMap map,int [] inorder) {
for(int i = 0;i<inorder.length;i++) {
map.put(inorder[i], i);
}
}
public static TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || inorder == null || preorder.length == 0) {
return null;
}
if(preorder.length == 1) {
return new TreeNode(preorder[0]);
}
init(map,inorder);
return myBuildTree(preorder,inorder,0,preorder.length-1,0,inorder.length-1);
}
public static TreeNode myBuildTree(int[] preorder, int[] inorder,int pstart,int pend,int istart,int iend) {
System.out.println("pstart:"+pstart+",pend:"+pend+",istart:"+istart+",iend:"+iend);
if(istart > iend || pstart > pend) {
return null;
}
if(istart == iend || pstart == pend) {
return new TreeNode(preorder[pstart]);
}
//前序的首位的值
int num = preorder[pstart];
TreeNode root = new TreeNode(num);
//前序的首位在中序中的位置
int index = map.get(num);
int len = index-istart;
root.left = myBuildTree(preorder, inorder, pstart+1, pstart+len, istart, index-1);
root.right = myBuildTree(preorder, inorder, pstart+len+1, pend, index+1, iend);
return root;
}