题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解决思路:
网上大多只给出一种思路,就是递归
一、递归
- 根据前序序列找出第一个结点确定根节点
- 根节点在中序序列中的位置分割出左右两个子序列
- 对左子树和右子树分别递归使用同样的方法继续分解
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length<1){
return null;
}
return f(pre, in, 0, pre.length-1, 0, in.length-1);
}
public static TreeNode f(int [] pre,int [] in,int p_s,int p_e,int i_s,int i_e) {
if(p_s>p_e||i_s>i_e){
return null;
}
TreeNode node =new TreeNode(pre[p_s]);
/**
* 寻找左子树的数组范围
* --左子树pre数组范围
* --左子树in数组范围
*/
int lp_s,lp_e;
int li_s,li_e;
int l_num=0;
// 左子树有几个元素
for(int i=i_s;i<=i_e;i++){
if(in[i]==pre[p_s]){
l_num=i-i_s;
break;
}
}
lp_s=p_s+1;
lp_e=lp_s+l_num-1;
li_s=i_s;
li_e=li_s+l_num-1;
node.left=f(pre, in, lp_s, lp_e, li_s, li_e);
/**
* 寻找右子树的数组范围
* --右子树pre数组范围
* --右子树in数组范围
*/
int rp_s,rp_e;
int ri_s,ri_e;
rp_s=lp_e+1;
rp_e=p_e;
ri_s=li_e+2;
ri_e=i_e;
node.right=f(pre, in, rp_s, rp_e, ri_s, ri_e);
return node;
}
利用Arrays.copyOfRange(oriArray,s,e),可以简化代码,使逻辑更清晰
// 利用Arrays.copyOfRange(s,e),左闭右开
public TreeNode reConstructBinaryTree1(int [] pre,int [] in) {
if(pre.length<1){
return null;
}
return f1(pre, in);
}
public static TreeNode f1(int [] pre,int [] in) {
if(pre==null||in==null){
return null;
}
if(pre.length<1||in.length<1){
return null;
}
TreeNode node =new TreeNode(pre[0]);
int l_num=0;
// 左子树有几个元素
for(int i=0;i<pre.length;i++){
if(in[i]==pre[0]){
l_num=i;
break;
}
}
if(l_num!=0){
node.left=f1(Arrays.copyOfRange(pre, 1, l_num+1),Arrays.copyOfRange(in, 0, l_num));
}
if(l_num<pre.length-1){
node.right=f1(Arrays.copyOfRange(pre, l_num+1, pre.length), Arrays.copyOfRange(in, l_num+1, in.length));
}
return node;
}