方法一:

分治+递归

思路: 二叉树的后序遍历顺序是:左子树 -> 右子树 -> 根节点 因此序列的最后一个数代表了根节点 因此我们可以将一个序列划分为3段, 左子树+右子树+根, 例如[4, 8, 6, 12, 16, 14, 10]可以根据根节点的值将其划分为左子树[4, 8, 6], 右子树[12, 16, 14], 根[10], 由于我们是先确定的右子树区间, 因此当左子树区间中出现大于根节点的值时, 序列不合法, 我们再采用分治的思想, 对于每段序列代表的子树, 检查它的左子树和右子树, 当且仅当左右子树都合法时返回true

代码:

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
       int n=sequence.size();
       //如果是空树,题目约定空树不是二叉搜索树
       if(n==0) return false;
       //后序:左右根(分治思想)+递归(后序遍历和二叉搜索树的递归定义)
       return devide(sequence,0,n-1);
    }
    //分治+递归
    bool devide(vector<int>&a,int l,int r){
        //递归的结束条件:如果这棵树只剩下一个节点,就返回true
        if(l>=r) {
            return true;
        }
        //划分区间的最后一个节点为根节点
        int root=a[r];
        //划分右子树:由于如果该树是二叉搜索树,则右树的节点的值大于根节点的值
        int j=r-1;
        while(j>=0&&a[j]>root) j--;
        //剩下的就是左子树,如果左子树中有节点的值大于根节点的值,那么就不是二叉搜索树
        int i=l;
        for(i=l;i<=j;i++){
            if(a[i]>root){
                return false;
            }
        }
        //由于二叉搜素树的递归定义,所以需要判断一下左右子树是否为二叉搜索树
        return devide(a,l,j)&&devide(a,j+1,r-1);
    }
};

方法二:

二叉搜索树对应的中序遍历是升序 中序:入栈,后序:某一种出栈顺序

思路:实际上二叉树的中序遍历和后序遍历对应着一种栈的压入、弹出序列, 而对后序遍历序列从小到大排序就得到了中序遍历序列 我们得到中序遍历序列后, 将其作为入栈序列, 检查后序遍历序列是不是一个合法的出栈序列即可 对于检查栈的合法压入、弹出序列问题, 请看栈的压入、弹出序列题解

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
      int n=sequence.size();
      //特判一下,题目约定空树不是二叉搜索树
      if(n==0) return false;
      //由于如果是二叉搜索树,那么其中序遍历是升序的
      vector<int> inorder(sequence);
      sort(inorder.begin(),inorder.end());
      return outorder(inorder,sequence);
    }
    //再将中序遍历压入栈中,看一下有没有满足后序的出栈顺序
    bool outorder(vector<int>inorder,vector<int>sequence){
        stack<int> stack1;
        int j=0;
        //遍历中序,将其对应的元素一个一个依次入栈
        //每入栈一个元素,就判断一下如果当前栈非空且栈顶元素与后序的元素对应,就出栈,并j++
        for(int i=0;i<inorder.size();i++){
             stack1.push(inorder[i]);
             while(!stack1.empty()&&stack1.top()==sequence[j]){
                j++;
                stack1.pop();
             }
        }
        //如果j==sequence.size(),就表明存在一种出栈顺序和后序遍历一致
        return j==sequence.size();
    }
};