面试题33:二叉搜索树的后序遍历序列
题目:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果,如果是返回true,不是返回false。
假设输入的数组任意两个数字互不相同。
思路:
首先。。。我忘了啥是二叉搜索树了囧
二叉搜索树:二叉树,且所有的子树都满足左小右大
百度百科:
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
算法思路:
后序遍历可知,对每颗树,在后序遍历中,都是其根节点在最后,如P180(第二版)中的树,如果只有1层和2层,则后序遍历是6-10-8,可见对二叉搜索树来说,其后序遍历都可由根节点,将其分为两个部分,一部分全比根节点小,另一部分全比根节点大。再对两个部分迭代进行判断。
举例说明:
如题目中所举的例子,{5,7,6,9,11,10,8}
① 8为根节点,可分为5,7,6 和9,11,10两个部分,对两个部分再进行判断
② 5-7-6部分,6为根节点,可分为5和7两部分,由于其都无子结点,不再进行迭代;对9-11-10部分,可分为9和11两个部分,同理不再进行迭代
所以该例子是满足条件的
另一例子{7,4,6,5},根节点为5,7-4-6无法划分,所以不为二叉搜索树的后序遍历序列
代码:
public class Q33 {
public static void main(String[] args) {
int[] a = new int[] {5,7,6,9,11,10,8};
int[] b = new int[] {7,4,6,5};
int[] c = new int[] {9,2,5};
System.out.println(tellBinarySearch(c));
}
public static boolean tellBinarySearch(int[] a) {
if(a.length<2) {
return true;
}
return tell(a, 0, a.length-1);
}
public static boolean tell(int[] a, int start, int end) {
if(start == end) {
return true;
}
// 找到分割数组的点
int n = a[end];
int left = start;
while(left<=end && a[left]<n) {
left++;
}
int right = end-1;
while(right>=0 && a[right]>n) {
right--;
}
if(right+1!=left) {
return false;
}
return tell(a, start, right) && tell(a, left, end-1);
}
}
// 2019-05-06
public class Q33 {
public static void main(String[] args) {
int[] a = new int[] {8,12,17,16,15,10};
int[] b = new int[] {7,4,6,5};
int[] c = new int[] {9,2,5};
boolean r = tellBinarySearch(c);
System.out.println(r);
}
public static boolean tellBinarySearch(int[] a) {
// 最开始为空,返回假
if(a.length==0) {
return false;
}
// 数组只有一个值,为根节点,返回真
if(a.length==1||a.length==2) {
return true;
}
// 数组长度大于2的情况
boolean left_,right_;
int loc = findLoc(a);
if(loc==-1) {
return false;
}
left_ = tellBinarySearch(Arrays.copyOfRange(a, 0, loc+1));
right_ = tellBinarySearch(Arrays.copyOfRange(a, loc+1, a.length-1));
return left_&right_;
}
// 对大于2的数组进行查找划分点
public static int findLoc(int[] a) {
int left = 0;
int right = a.length-1;
int end = a[right--];
while(a[right]>end) {
right--;
}
while(a[left]<end) {
left++;
}
if(right+1==left) {
return right;
}
return -1;
}
}