Construct binarysearch tree from inorder & postorder Or preorder 利用中序遍历和前序遍历或后续遍历构建二叉搜索树
这一题其实也是leetcode中关于BST(Binary search Tree)的经典题型了,这一道就是给我们两个数组分别代表了一个BST的中序遍历和前序(另一题给的是后序遍历),为什么没有前序遍历和后序遍历的题呢?因为只给出前序遍历和后序遍历是无法确定唯一的BST的,但是前序+中序或者是后序+中序就可以。
让我们先看看前序遍历+中序遍历的解题思路吧。首先我们了解一下前序遍历和中序遍历
前序遍历的顺序就是:根->左->右
中序遍历的顺序是:左->根->右
当我们了解了两种遍历的顺序之后就知道,其实我们只需要根据前序遍历里面的第一个元素找找到在中序遍历里面的位置就可以成功的把树分出左右了,然后再递归的分治法来解决这个问题,就可以很好的完成了,让我们看看java的实现吧
class Construct{
Map<Integer,Integer> map;
//用于存放元素在中序遍历里面的位置索引
public TreeNode buildTree(int[] inorder, int[] preorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length;i++){
map.put(inorder[i],i);
//存放在中序遍历里的索引
}
return helper(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
private TreeNode helper(int[] preorder, int pStart, int pEnd, int[] inorder, int iStart, int iEnd){
if(pStart>pEnd || iStart > iEnd)return null;
int index = map.get(preorder[pStart]);
//找到当前的根节点在中序遍历中的位置
int leftSum = index-iStart;
//确定以当前节点为根节点的左子树的节点个数
TreeNode root = new TreeNode(preorder[pStart]);
//将前序遍历的指针+1移动到左子树的第一个节点,尾部移动到左子树的最后一个而节点
//将中序遍历的尾部移动到当前的根节点,在其左侧所有节点都是其左子树的节点
root.left = helper(preorder,pStart+1,pStart+leftSum,inorder,iStart,index);
//将前序遍历的指针移动到左子树的最后一个节点+1,也就是右子树的根节点,尾部依然是数组的结尾
//将中序遍历的起点移动到根节点+1,包括当前节点在内的所有右侧节点都是根节点的右子树节点。
root.right = helper(preorder,pStart+leftSum+1,pEnd,inorder,index+1,iEnd);
return root;
}
}
这样我们就可以很轻松解决利用前序遍历和中序遍历来构建唯一BST的实现了。
再让我们看看如果是中序遍历和后序遍历我们应该怎么样处理,首先让我们来看看后序遍历和前序遍历的差别后序遍历的顺序是:左->右->根
所以根节点是后序遍历数组的最后一个节点。但是中序遍历依然是一样的,但是再左右子树的指针变化上会稍有不同,让我们看看Java实现吧。
class Solution {
Map<Integer,Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length;i++){
map.put(inorder[i],i);
//一样是存入元素再中序遍历里位置的索引
}
return helper(postorder,0,postorder.length-1,inorder,0,inorder.length-1);
}
private TreeNode helper(int[] postorder, int pStart, int pEnd, int[] inorder, int iStart, int iEnd){
if(pStart > pEnd || iStart > iEnd){
return null;
}
int index = map.get(postorder[pEnd]);
//找到根节点再中序遍历里的位置
TreeNode root = new TreeNode(postorder[pEnd]);
int leftNum = index-iStart;
//计算当前节点的左子树的节点数
//将指向后序遍历的指针移动到所有左子树的最后一个节点,中序遍历与前一题相同
root.left = helper(postorder,pStart,pStart+leftNum-1,inorder,iStart,index);
//将指向后序遍历的指针移动到右子树的第一个节点,根节点的指针向后移动,中序遍历和前一题相同
root.right = helper(postorder,pStart+leftNum,pEnd-1,inorder,index+1,iEnd);
return root;
}
}
这样我们就只需要做出一点点的改动就可以完成利用后序遍历和中序遍历也构建唯一的BST了。