题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
分析:
二叉搜素树指的是根节点的左子树的值都比根节点的值小,而右子树的结点的值都比根节点的值大。若给出的是数组是二叉搜索树的后序遍历,则最后一个值为根节点,如下图所示。
法一:
若是二叉搜索树的后序遍历,从根节点5开始,5前面的数先一直比它小(2、4、3),后一直比它大(6、9、8),不会存在比它大小混杂的情况(2、6、3、8),所以若5之前的数先是一直比它小,后一直比它大,则节点5满足条件,再依次判断5前面的节点是否满足该条件。由于数组元素要两两比较,因此时间复杂度为
public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
int len = sequence.length;
if(len <= 0)
return false;
int count = 0;
while(len > 0 ){
while(sequence[count] < sequence[len-1])
count++;
while(sequence[count] > sequence[len-1])
count++;
if(count != len-1)
return false;
count = 0;
len--;
}
return true;
}
}
法二:
方法一进行了多次重复性的比较,其实如果能知道根节点的左子树和右子树,就不需要将其左子树的值再与右子树的值比较了,只需要分别将左子树和右子树再分别作为独立的数进行递归判断即可。而左子树的与右子树的分界点很好找,只要找到数组中第一次比根节点值大的值即可,由于分组递归判断,时间复杂度为。
public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
if(sequence.length <= 0)
return false;
return bst(sequence, 0, sequence.length-1);
}
public boolean bst(int [] sequence, int begin, int end) {
int root = sequence[end];//最后一个值为根节点
int p = begin;//用于记录左子树和右子树的分界点
for(; p < end; p++){
if(sequence[p] > root)
break;
}
//若分界点右边存在比根节点小的值即不满足
for(int j = p; j < end; j++){
if(sequence[j] <= root)
return false;
}
//递归判断左子树
boolean left = true;
if(p > begin)//此处考虑临界点的情况,即若p与begin相等,则不继续递归判断
left = bst(sequence, begin, p-1);
//递归判断右子树
boolean right = true;
if(p < end-1)
right = bst(sequence, p, end-1);
return (left && right);
}
}