解题思路:

1、根据二叉搜索树的后续遍历规律:左子树--右子树--根;序列最后一个元素为根节点,左子树的元素值都小于根节点,右子树的元素值都大于根节点。
(1)将数组的元素分为两部分:左子树序列值和右子树序列值,左子树值都小于根节点值,右子树值都大于根节点值
(2)分别对左右子树序列值进行(1)方法递归,如果递归过程中发现其右子树序列中有值小于根节点值,则不是一个后续序列
2、采用单调栈的形式解题
(1)初始化: 单调栈 stack ,父节点值 root(初始值为正无穷大,可把树的根节点看为此无穷大节点的左孩子);
(2)倒序遍历数组:记每个节点为 ri ,判断: 若 ri > root ,说明此后序遍历序列不满足二叉搜索树定义,直接返回false ;
(3)更新父节点 root: 当栈不为空 且 ri < stack.peek() 时,循环执行出栈,并将出栈节点赋给 root 。
(4)入栈: 将当前节点 ri 入栈;
(5)若遍历完成,则说明后序遍历满足二叉搜索树定义,返回 true。

举例说明:
数组:【4,8,6,12,16,14,10】
(1)根节点为10,左子树为【4,8,6】,右子树为【12,16,14】
(2)分别对左右子树进行递归;针对左子树时,左子树的根节点为6,其左子树为【4】,其右子树为【8】,则该左子树符合后续遍历规则
(3)针对右子树时,左子树的根节点为14,其左子树为【12】,其右子树为【16】,则该右子树也符合后续遍历规则,则该数组是二叉搜索树的后序遍历序列

图表展示:
步骤 数组序列 根节点 左子树
右子树
1 4,8,6,12,16,14,10
【10】 4,8,6 【12,16,14】
2 4,8,6
【6】 【4】 【8】
3 【12,16,14】
【14】 【12】 【16】
根据图表步骤展示,该数组的左右子树都符合二叉搜索树的后序遍历规则,因此该数组
二叉搜索树的后序遍历序列

代码展示:

Python版本:
# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        if not sequence:
            return False
        # 递归
        return self.check(sequence, 0, len(sequence) - 1)

    def check(self, sequence, left, right):
        if left >= right:
            return True
        # 找到第一个大于根节点的元素
        mid = left
        root = sequence[right]
        while sequence[mid] < root: mid += 1 tmp = mid # 保障postorder[mid]后的数要大于root,否则返回false while tmp < right: tmp += 1 if sequence[tmp] < root: return False # 递归左右子树进行判断 return self.check(sequence, left, mid - 1) and self.check(sequence, mid, right - 1)

Java版本:
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        // 判断是否师空序列
        if (sequence.length == 0){
            return false;
        }
        return dfs(sequence, 0, sequence.length);
    }
    
    private boolean dfs(int[] sequence, int start, int end) {
        if (start >= end - 1)
            return true;
        // 根结点是最后一个元素
        int root = sequence[end - 1];
        // 左子树都比根结点小,右子树都比根结点大
        int i = start;
        while (i < end && sequence[i] < root) // i 为左右子树的边界 ++i; // 判断右子树是否比根节点大 for (int j = i; j < end; ++j) if (sequence[j] < root) return false; // 对序列的前后两部分进行递归调用 return dfs(sequence, start, i) && dfs(sequence, i, end - 1); } }
复杂度分析:
时间复杂度 O(N^2): 每次调用 递归算法减去一个根节点,因此递归占用 O(N) ;最差情况下(即当树退化为链表),每轮递归都需遍历树所有节点,占用 O(N) 。
空间复杂度 O(N): 最差情况下(即当树退化为链表),递归深度将达到 N