题目描述:
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
利用二叉树的中序和后序的序列还原一颗二叉树。
注:
你可以假设树中不存在重复项。
思路:遍历后序数组,根据每个数在中序数组下标的大小来找到其位置。(这个是非递归版的,递归会比较慢)
public class ConstructBinaryTreefromInorderandPostorderTraversal {
public static int Inorder[]={4,7,2,1,9,5,3,6,8};//中序数组
public static int Postorder[]={7,4,2,9,5,8,6,3,1};//后序数组
//获得后序数组中的数字在中序数组对应下标
public static int getIndex(int num)
{
for(int i=0;i<Inorder.length;i++)
{
if(num==Inorder[i])
return i;
}
return -1;
}
public static void solve()
{
//根节点的中序下标
int root=getIndex(Postorder[Postorder.length-1]);
//存储已经遍历过的点
ArrayList<Node> queue=new ArrayList<Node>();
//新建根节点
Node rootnode=new Node(Postorder[Postorder.length-1]);
queue.add(rootnode);
//用来判断是否将根节点的右子树遍历完
boolean judge=true;
//遍历后序数组
for(int i=Postorder.length-2;i>=0;i--)
{
//每个数的下标
int index1=getIndex(Postorder[i]);
//遍历根节点的左子树时要对队列做一个清空
if(index1<root&&judge)
{
queue.clear();
queue.add(rootnode);
judge=false;
}
//作为一个标记,来确定节点的方向
int mark=getIndex(queue.get(0).value);
//遍历已经遍历过的节点队列
for(int j=0;j<queue.size();j++)
{
//已经遍历过的节点的下标
int index2=getIndex(queue.get(j).value);
//这个判断很重要,这个判断最主要的作用是确保叶子节点的大方向(到底在左右子树哪个上)的正确
if((index1>mark&&index2>=mark)||(index1<mark&&index2<=mark))
{
mark=index2;
if(index1>index2&&queue.get(j).Right==null)
{
System.out.println(queue.get(j).value+"右节点是"+Postorder[i]);
Node node=new Node(Postorder[i]);
queue.get(j).Right=node;
queue.add(node);
break;
}
if(index1<index2&&queue.get(j).Left==null)
{
System.out.println(queue.get(j).value+"左节点是"+Postorder[i]);
Node node=new Node(Postorder[i]);
queue.get(j).Left=node;
queue.add(node);
break;
}
}
}
}
}
public static void main(String[] args) {
solve();
}
}
class Node
{
public Node(int i)
{
value=i;
}
int value;
Node Left;
Node Right;
}