题目
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。
思路
首先收集二叉搜索树的特点,所有非叶子节点的左子节点的值必须小于该节点,同比类推右子节点的值大于该节点,后序遍历就是先按 左子树-右子树-中间节点 的顺序遍历的,据此可以推断出以下结论:
所有二叉搜索树的后序遍历都必须满足:(小于根节点的数集)(大于根节点的数集)根节点 这种形式(为了方便下面用“小区间”,“大区间”分别代指“小于根节点的数集”和“大于根节点的数集”)
小区间和大区间都是可以同时存在,同时不存在,也可以同时只存在一个
整理一下
所有符合要求的可能性有
1.(小区间)(大区间)根节点
2.(小区间)根节点
3.(大区间)根节点
4.根节点
5.null
不符合要求的很显然就是
(大区间)(小区间)根节点
这种可能性了
代码
public class Solution {
public boolean verifySquenceOfBST(int [] sequence) {
if(sequence.length == 0) return false;
if(sequence.length < 3){//只有1到两个元素的肯定能组成二叉搜索树
return true;
}else{
return verifySquenceOfBST(sequence,0,sequence.length-1);
}
}
private boolean verifySquenceOfBST(int[] sequence, int start, int end) {
if((end - start) < 2) return true;
int i = end - 1;
boolean result = false;
int lessAreaRight = -1; //小区间右边界
for(;i>start-1;i--){
if(sequence[i] < sequence[end]){
if(lessAreaRight == -1){
lessAreaRight = i;//第一个小于根节点的数的下标
}
}
if(lessAreaRight != -1){
//小区间右边界存在的情况下,说明再往左都应该是小于根节点的
//若在小区间中出现了大于根节点的值,说明不符合要求
if(sequence[i] > sequence[end])
return false;
}
}
//能走到这说明满足(小区间)(大区间)根节点这一要求
if(lessAreaRight != -1){//小区间存在
//递归判断小区间是否满足要求
result = verifySquenceOfBST(sequence,start,lessAreaRight);
if(result){
//这里大区间不一定存在,但一定要进行判断
//递归判断大区间是否满足要求
result = verifySquenceOfBST(sequence,lessAreaRight+1,end-1);
}
}else{
//小区间不存在,说明只存在大区间
//递归判断大区间是否满足要求
result = verifySquenceOfBST(sequence,start,end-1);
}
return result;
}
}