输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
重建二叉树的更具给出的两个列表重建出二叉树(不能没有中序遍历)。
前序(后序)遍历能确定出根节点。中序遍历能确定出左右子树的所有节点。
思路一:递归实现,处理将情况分为左子树和右子树实现。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution{
public TreeNode buildTree(int[] preorder, int[] inorder) {
//preorder前序遍历 inorder中序遍历
if(preorder==null||preorder.length==0){
return null;
}
Map<Integer,Integer> hashMap=new HashMap<Integer,Integer>();
//hashMap可以快速读取出中序遍历的位置。
int length=preorder.length;
for (int i=0;i<inorder.length;i++){
hashMap.put(inorder[i],i);//这里是节点值在前,其在列表的顺序在后
}
return treeBuild(preorder,0,length-1,inorder,0,length-1,hashMap);
}
public TreeNode treeBuild(int[] preorder,int pStart,int pEnd,int[] inorder,int iStart,int iEnd,Map<Integer,Integer> hashMap){
if(pStart>pEnd){//当前为叶子节点(java中二叉树的叶子节点一部分为null节点)
return null;
}
int nodeVal=preorder[pStart];//获取当前需要处理的节点值
TreeNode treeNode=new TreeNode(nodeVal);//实例化本节点。
if(pStart==pEnd){//当前节点为叶子节点
return treeNode;//每个方法栈会返回一个节点的值(也就是说时间复杂度O(N),空间复杂度O(n))
}else{
int nodeIndex=hashMap.get(nodeVal);//获取当前节点的位置
int leftNodes=nodeIndex-iStart,rightNodes=iEnd-nodeIndex;
//leftnodes确定出当前节点的所有左子节点数量,rightnodes确定出当前节点的右子节点数量
TreeNode leftTree=treeBuild(preorder,pStart+1,pStart+leftNodes,inorder,iStart, nodeIndex-1,hashMap);
//这个递归操作出当前节点的左子树节点,这里就可以说明刚才的是确定的是节点的数量
TreeNode rightTree=treeBuild(preorder,pEnd-rightNodes+1,pEnd,inorder,nodeIndex+1, iEnd,hashMap);
//这个递归操作出当前节点的右子树节点
treeNode.left=leftTree;//将结果添加到当前节点
treeNode.right=rightTree;//将结果添加到当前节点
return treeNode;//每个方法栈会返回一个节点的值
}
}
}
思路二:利用栈的特性实现重构二叉树
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0) {
return null;
}
TreeNode root = new TreeNode(preorder[0]);
int length = preorder.length;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
int inorderIndex = 0;
for (int i = 1; i < length; i++) {
int preorderVal = preorder[i];
TreeNode node = stack.peek();
if (node.val != inorder[inorderIndex]) {
node.left = new TreeNode(preorderVal);
stack.push(node.left);
} else {
while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
node = stack.pop();
inorderIndex++;
}
node.right = new TreeNode(preorderVal);
stack.push(node.right);
}
}
return root;
}
}