二叉搜索树的后序遍历序列
问题
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
思路
以{5,7,6,9,11,10,8}为例,后序遍历结果的最后一个数字8就是根结点的值。在这个数组中,前3个数字5、7和6都比8小,是值为8的结点的左子树结点;后3个数字9、11和10都比8大,是值为8的结点的右子树结点。
我们接下来用同样的方法确定与数组每一部分对应的子树的结构。这其实就是一个递归的过程。对于序列5、7、6,最后一个数字6是左子树的根结点的值。数字5比6小,是值为6的结点的左子结点,而7则是它的右子结点。同样,在序列9、11、10中,最后一个数字10是右子树的根结点,数字9比10小,是值为10的结点的左子结点,而11则是它的右子结点。
我们使用递归的方法,先判断数组的左子树和右子树的位置,然后再判断左子树、右子树是不是二叉搜索树。
public class Solution {
/**二叉搜索树的性质:
* 所有左子树的节点小于根节点,所有右子树的节点值大于根节点的值。
* 算法步骤:
* 1.后序遍历的最后一个值为root,在前面的数组中找到第一个大于root值的位置。
* 2.这个位置的前面是root的左子树,右边是右子树。然后左右子树分别进行这个递归操作。
* 3.其中,如果右边子树中有比root值小的直接返回false
* @param sequence
* @return
*/
public boolean VerifySquenceOfBST(int [] sequence) {
if (sequence == null || sequence.length == 0)
return false;
return IsBST(sequence, 0, sequence.length -1);
}
public boolean IsBST(int [] sequence, int start, int end) {
if(start >= end)
//注意这个条件的添加
// 如果对应要处理的数据只有一个或者已经没
//有数据要处理(start>end)就返回true
return true;
int index = start;
for (; index < end; index++) {
//寻找大于root的第一个节点,然后再分左右两部分
if(sequence[index] > sequence[end])
break;
}
for (int i = index; i < end; i++) {
//若右子树有小于根节点的值,直接返回false
if (sequence[i] < sequence[end]) {
return false;
}
}
return IsBST(sequence, start, index-1) && IsBST(sequence, index, end-1);
}
}
public boolean verifySquenceOfBST(int sequence[]){
if(sequence == null){
return false;
}
return verifySquenceOfBST1(sequence, 0, sequence.length - 1);
}
private boolean verifySquenceOfBST1(int[] sequence, int start, int end) {
if(start >= end){
return true;
}
int root = sequence[end]; //后序遍历的最后一个结点为根结点
//在二叉搜索树中左子树的结点小于根结点
int i = 0;
for(; i < end; ++i){
if(sequence[i] > root){
break;
}
}
//在二叉搜索树中右子树的结点大于根结点
int j = i;
for(; j < end; ++j){
if(sequence[j] < root){
return false;
}
}
//判断左子树是不是二叉树
boolean left = true;
if(i > start){
left = verifySquenceOfBST1(sequence, start, i-1);
}
//判断右子树是不是二叉树
boolean right = true;
if(i < end){
right = verifySquenceOfBST1(sequence, i, end -1);
}
return (left && right);
}