作者 | 小鹿
来源 | 小鹿动画学编程
题目
输入一个整数数组,判断该数组是不是某二叉搜索树的后续遍历。如果是返回 true,如果不是返回 false。假设输入的任意两个数字互不相同。
如图:
问题分析
我们要解决这个面试题之前我们要回顾一下后序遍历以及二叉树的特点。相信各位已经对二叉树已经熟烂于心了,后序遍历的特点就是先遍历左子节点,然后遍历右子节点,最后遍历根节点。
对于二叉树的特点,对你来说更为简单,二叉树中有一个特点就是左子树比根节点小,所有的右子树比根节点大。
如果这两个特点你很容易的知道,那么这道题基本已经完成了,剩下就是通过递归来写代码了,大体的思路我们还是需要罗列一下。
通过二叉树的后序遍历知道,后序遍历的数组最后一个数就是整棵二叉树的根节点,我们通过左子树、右子树以及和根节点的关系,我们遍历数组,找出大小分隔的界限,然后进行递归,整道题解决完毕。具体分析看一下动画和详细解析。
动画实现
解题思路
首先,判断传入的后续遍历数组是否为空,之后取出数组的最后一个元素为根节点。
1// 判断当前数组是够为空
2 if (arr.length === 0) return false;
3
4 // 声明变量
5 let length = arr.length;
6 let root = arr[length-1];
7 let mid = 0;
8 let flag = false;
在数组中找出第一个大于根节点的值,就是根节点的右子树起始的位置下标。
1 // 找出大于根节点的第一个节点,并记录其下标
2 for (let i = 0; i < length; i++) {
3 if (root < arr[i]) {
4 mid = i;
5 flag = true;
6 break;
7 }
8 }
为了验证右子树是否都是大于根节点的值,所以遍历右子树,检查是否有小于根节点的值,如果有,则后序遍历不成立构成二叉树。
1 // 找到大于根节点的数据中是否存在小于根节点的数据吗,在上边满足的条件下
2 // 否则返回 false
3 for (let i = mid; i < length; i++){
4 if (root > arr[i] && flag) {
5 return false;
6 }
7 }
开始进行分割左右子树进行递归判断所有的左右子树节点。
1 let left = true;
2 let right = true;
3
4 // 左子树递归
5 if (mid > 0) {
6 left = VerifySquenceOfBST(arr.slice(0, mid));
7 }
8
9 // 右子树递归
10 if (mid < arr.length-1){
11 right = VerifySquenceOfBST(arr.slice(mid, length-1));
12 }
13
14 // 返回判断是否为某后续遍历的二叉树
15 return left && right;
代码实现
JavaScript
Java
Python
测试用例
完全二叉树、不完全二叉树 —— 普通测试
只有左子节点的二叉树、只有右子节点的二叉树、只有一个节点的二叉树 —— 特殊测试
空树 —— 输入测试