涉及到树的基础。
前序 遍历,就是先遍历根部,在遍历左子节点和右子节点。
中序是先遍历左子树,再遍历根部,最后遍历右子节点。
所以在前序给出的第一数字就是根节点。然后在中序遍历中,找到这个数,那么这个数的左边,都是这个根节点的左子树。
第一步要在前序遍历中找到第一个节点。
第二步从中序遍历中找到这个节点。
第三步找到左子树右子树
第四步递归循环
package question7_build_tree;
/**
* @Classname Solution2
* @Description TODO
* @Date 2020/3/31 15:28
* @Created by mmz
*/
public class Solution2 {
static class TreeNode{
int root;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int root) {
this.root = root;
}
@Override
public String toString() {
return "TreeNode{" +
"root=" + root +
", left=" + left +
", right=" + right +
'}';
}
}
static TreeNode rebuildTree(int[] front,int frontstart,int frontend,int[] middle,int middlestart,int middleend){
if(frontstart>frontend ||middlestart>middleend){
return null;
}
TreeNode root = new TreeNode(front[frontstart]);
int index = 0;
for(int i = middlestart;i<=middleend;++i){
if(front[frontstart] == middle[i]){
index = i;
break;
}
}
root.left = rebuildTree(front,frontstart+1,frontstart+index-middlestart,middle,middlestart,index-1);
root.right = rebuildTree(front,frontstart+index+1,frontend,middle,index+1,middleend);
return root;
}
public static void main(String[] args) {
int[] pre =new int[]{1,2,4,7,3,5,6,8};
int[] mid = new int[]{4,7,2,1,5,3,8,6};
System.out.println(rebuildTree(pre,0,pre.length-1, mid,0,mid.length-1));
}
}
这题有一个问题,就是这个7这个节点,是4的右子树还是2的右子树呢。这样都能说得过去,是不是说明如果知道了前序与中序遍历,也不能确定这个二叉树的形状呢。
package question7_重建二叉树根据前序和中序;
/**
* @Classname Main
* @Description TODO
* @Date 2020/4/11 15:21
* @Created by mmz
*/
public class Main {
public static class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int val){
this.val = val ;
}
@Override
public String toString() {
return "TreeNode{" +
"val=" + val +
", left=" + left +
", right=" + right +
'}';
}
}
public static TreeNode Core(int[] front,int fs,int fe, int[] mid,int ms,int me){
if(fs>fe || ms>me){
return null;
}
TreeNode root = new TreeNode(front[fs]);
int index =0;
for(int i= 0;i<front.length;++i){
if(front[fs] == mid[ms+i]){
index = i;
break;
}
}
root.left = Core(front,fs+1,fs+index,mid,ms,ms+index-1);
root.right = Core(front,fs+index+1,fe,mid,ms+index+1,me);
return root;
}
// private static TreeNode help(int[] preorder, int pStart, int pEnd, int[] inorder, int iStart, int iEnd) {
// //递归的第一步:递归终止条件,避免死循环
// if (pStart > pEnd || iStart > iEnd) {
// return null;
// }
// //重建根节点
// TreeNode treeNode = new TreeNode(preorder[pStart]);
// int index = 0; //index找到根节点在中序遍历的位置
// while (inorder[iStart + index] != preorder[pStart]) {
// index++;
// }
// //重建左子树
// treeNode.left = help(preorder, pStart + 1, pStart + index, inorder, iStart, iStart + index - 1);
// //重建右子树
// treeNode.right = help(preorder, pStart + index + 1, pEnd, inorder, iStart + index + 1, iEnd);
// return treeNode;
//
// }
public static void main(String[] args) {
int[] pre =new int[]{1,2,4,7,3,5,6,8};
int[] mid = new int[]{4,7,2,1,5,3,8,6};
System.out.println(Core(pre,0,pre.length-1,mid,0,mid.length-1));
// System.out.println(help(pre,0,pre.length-1,mid,0,mid.length-1));
}
}
自己完整的写出来了,问题在于index的计算,是往上加好呢,还是直接得到根节点的索引,我发现,还是index是用计数器内种,往上加好算,这样可以判断,进行遍历啊。
至于前序和中序数组的循环条件。
前序的左子节点,永远是fs+1,fs+index
中序是ms,ms+index-1
一定记住两个左右子树的判断条件
left = 前序数组 数组fs+1 fs+index
中序数组 数组ms ms+index-1
right = 前序数组 数组fs+index+1 fe
中序数组 数组ms+index+1 me
return完事