这个题有一个非常诡异的地方。在一般的根据树结构判断是否为二叉树的问题中,这种情况:
是一定要特别注意的,如果用普通的dfs判断左、右子树是否小于、大于根节点,会把这颗树误判为二叉搜索树。
然而,如果仅给出一棵树的前序序列,让你判断是否是二叉搜索树,这种情况判为正确也是没问题的。因为它的前序序列,43165,还可以表示为下图的树:
这颗树是二叉搜索树。如果一个序列可以认为是BST,也可以不是BST,那么它就是BST···pta上的这一题是这么ac的。
也因此 前序序列无法唯一表示一颗二叉树(后序序列也不行。)
下面是由前序序列判断是否为BST的算法:
方法 isBST(int root,int tail)递归判断一棵树的左子树是否都小于根节点,右子树是否都大于根节点。
参数中的root表示为当前树的根节点,tail表示为最后一个结点。
方法体中的i、j, 分别初始化为根节点的下一个结点、当前树的最后一个节点。经过操作后,如果当前树是二叉排序树,则i为右子树第一点,j为左子树最后一点。因此如果i!=j+1,则该树不是二叉排序树。
如果是的话,继续进行左右子树遍历。
具体见代码。
public class Main {
static int DLR[]=new int[1010];
static ArrayList<Integer> LRD=new ArrayList<Integer>();
static boolean isBST(int root,int tail) {//root为当前树根节点下表,tail为当前树最后一个节点下标
if(root>tail) {
return true;
}
int i=root+1;
int j=tail;
while(i<=tail&&DLR[i]<DLR[root]) {
i++;
}
while(j>root&&DLR[j]>=DLR[root]) {
j--;
}
if(j+1!=i) {
return false;
}
if(!isBST(root+1,j)) {
return false;
}
if(!isBST(i,tail)) {
return false;
}
LRD.add(DLR[root]);
return true;
}
static boolean reBST(int root,int tail) {
//基本同上一个方法
}
static PrintWriter out=new PrintWriter(System.out);
static void print() {
for(int i=0;i<LRD.size();i++) {
if(i!=0) {
out.print(" ");
}
out.print(LRD.get(i));
}
out.flush();
out.close();
}
public static void main(String args[]) {
InputReader sc=new InputReader(System.in);
int N=sc.nextInt();
for(int i=0;i<N;i++) {
DLR[i]=sc.nextInt();
}
if(isBST(0, N-1)) {
out.println("YES");
print();
}else {
LRD.clear();//清空链表的操作一定不要忘了!!
if(reBST(0, N-1)) {
out.println("YES");
print();
}else {
out.println("NO");
out.flush();
out.close();
}
}
}
}