输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
假设给定的序列是[4,6,7,5],根据二叉搜索树的性质以及后序遍历的规律,我们不难得出下面这样的树:
- 二叉搜索的左孩子都小于父节点,二叉搜索树的右孩子都大于父节点
- 后序遍历的顺序是
左-->右-->根
5
/ \
4 7
/
6
根据上面的思路,我们可以得出这样的思路:
- 数组最后一个元素是根节点(后序遍历)
- 由二叉搜索树的性质,左子树所有的节点都小于根节点.
- 后序遍历总是先遍历完左子树,再遍历右子树,所以左右子树的边界是第一个大于根节点的元素。
我们再来看一个复杂点的例子[4,8,6,12,16,14,10]
这里先给出树结构。
10
/ \
6 14
/ \ / \
4 8 12 16
根据上面的分析,我们很容易知道[4,6,8]是左子树,[12,16,14]是右子树。
root = 10
left = [4,8,6]
right = [12,16,14]
// 因为二叉搜索树的子树同样是一颗二叉搜索树,所以我们重复上述步骤
**************
对于左子树来说
root = 6
left = [4] //只有一个元素说明到达叶子结点
right = [8]
**************
对于右子树来说
root = [14]
left = [12]
right = [16]
**************
我们发现,根据序列生成的树符合二叉搜索树的定义,所以结果为true
这些都是符合条件的遍历结果,那不符合条件的呢?
我们将上面的例子稍微修改一下,假设给定的序列是:[4,12,8,6,16,14,10]
root = 10;
left = [4]
right = [12,8,16,14]
**********
对于左子树来说,很容易判断是满足二叉搜索树的。
对于右子树
right = [12,8,16,14]中有一个元素小于 root(10),不符合条件,因此这不是一棵二叉搜索树,直接返回false.
假设right = [12,20,18,11] 全部都大于root(10),但它并不是一颗二叉搜索树
11
/
18
/\
12 20
因此我们需要进行递归判断.
通过上面的分析,我们也可以知道,我们只需要判断右子树是不是一棵二叉搜索树就可以了。
于是我们很轻松就写出下面的函数
function VerifySquenceOfBST(sequence)
{
if(!sequence.length){
return false
}
let root = sequence.pop() //5
let start = sequence.findIndex((val)=>{
return val>root
})
return start===-1?true:isBST(root,sequence.slice(start))
function isBST(root,tree){ //root 5 tree[1,2,3,4]
if(!tree.length){ // 如果数组数为空,则返回true
return true
}
let index = tree.findIndex((val)=>{ //index === -1
return val<root
})
if(index != -1){
return false
}
root = tree.pop() //root 7 tree[6]
let start = tree.findIndex((val)=>{
return val>root //
})
return tree.length===1?true:isBST(root,tree.slice(start))
}
}