这道题关键在于判断一棵树是不是 BST
现在题目给出了树的先序序列——我们可以知道这棵树的根,然后题目也给出了 BST 的定义——左子树 < 根 ≤ 右子树(BST 镜像则是 左子树 ≥ 根 > 右子树),那么就可以确定左子树、根、右子树,从而确定这棵二叉树。
所以我们可以通过根和根后续结点确定这棵树是 BST 还是 BST 镜像。如果是 BST,那么后面的子树也要全是 BST;否则后面的子树全是 BST 镜像
所以大概的思路就出来了:
/* 伪码 */ int tree[maxn];//保存输入 bool flag = true;//由于判断是否满足 BST 特性需要所有子树都满足才真正满足条件,而遍历涉及递归不太好返回,所以设置个标志位用来判断 void traversal(当前结点 n, 左子树起始下标 base, 右子树结束下标 end) { /* 死胡同 */ if (base == end) {//叶子结点 n->data = tree[base]; n->left = n->right = NULL; return; } /* 确定左子树与右子树 */ if (tree[base + 1] < n->data) {//左子树比根小 //利用 BST 特性找到 tree[] 中第一个大于等于根的就是左右子树分界 } else { //同理 } if (l - 1 != r) flag = false;//如果这个分界不是相差 1, 那就不满足 /* 递归式 */ traversal(n->left, base, 分界线 - 1); traversal(n->right, 分界线, end); }
遗憾的是,最后程序 PA。我在 debug 时发现了一例逻辑错误的例子,留着后面再回顾了:
/* 暂时发现了一个逻辑错误的例子: 5 2 4 3 5 1 无论是 BST 还是 BST 镜像最后输出应该是 "NO" 而目前程序输出 "YES" 错误原因是: (如果按 BST 来组织)既然 [1] 比 [0] 大,那么 [1] 后面的结点应该全是右子树————全比 [0] 大;
(如果按 BST 镜像来组织)既然 [1] 比 [0] 大,那么 [1]~[3] 应该是左子树————但这棵左子树又不满足 BST 特性 修改了很久都没改出来,所以先放着 :-( */