二叉搜索树的后序遍历序列[剑指offer]

475 阅读3分钟

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出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))
    }
}