🚩传送门:力扣题目

题目

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 [LC]33. 二叉搜索树的后序遍历序列 - 图1,否则返回 [LC]33. 二叉搜索树的后序遍历序列 - 图2
假设输入的数组的任意两个数字都互不相同。

参考以下这颗二叉搜索树:

  1. 5
  2. / \
  3. 2 6

/ \ 1 3

示例 1:

输入: [1,6,3,2,5] 输出: false

示例 2:

输入: [1,3,2,6,5] 输出: true

解题思路:递归

后序遍历定义: [ 左子树 | 右子树 | 根节点 ] ,即遍历顺序为 “左、右、根”
[LC]33. 二叉搜索树的后序遍历序列 - 图3
二叉搜索树定义:

  1. 左子树中所有节点的值 < 根节点的值;
  2. 右子树中所有节点的值 > 根节点的值;
  3. 其左、右子树也分别为二叉搜索树。

算法思想:遍历区间划分左右子树,递归左右子树检查是否为二叉搜索树

  1. 划分左右子树
  • 后续遍历数组[LC]33. 二叉搜索树的后序遍历序列 - 图4[LC]33. 二叉搜索树的后序遍历序列 - 图5区间,根结点一定是[LC]33. 二叉搜索树的后序遍历序列 - 图6元素
  • 遍历数组[LC]33. 二叉搜索树的后序遍历序列 - 图7[LC]33. 二叉搜索树的后序遍历序列 - 图8区间区间元素,寻找 第一个大于根节点 的节点,索引记为 [LC]33. 二叉搜索树的后序遍历序列 - 图9此时左子树区间 [LC]33. 二叉搜索树的后序遍历序列 - 图10右子树区间 [LC]33. 二叉搜索树的后序遍历序列 - 图11
  1. 判断是否为二叉搜索树

    左子树有上限 [LC]33. 二叉搜索树的后序遍历序列 - 图12,右子树有下限[LC]33. 二叉搜索树的后序遍历序列 - 图13

  • 左子树区间 [LC]33. 二叉搜索树的后序遍历序列 - 图14 内的所有节点值都应该在范围[LC]33. 二叉搜索树的后序遍历序列 - 图15
  • 右子树区间 [LC]33. 二叉搜索树的后序遍历序列 - 图16 内的所有节点值都应该在范围[LC]33. 二叉搜索树的后序遍历序列 - 图17

复杂度分析

时间复杂度:[LC]33. 二叉搜索树的后序遍历序列 - 图18,最差情况下(即当树退化为链表),每轮递归都需遍历树所有节点

空间复杂度:[LC]33. 二叉搜索树的后序遍历序列 - 图19 最差情况下(即当树退化为链表),递归深度将达到 [LC]33. 二叉搜索树的后序遍历序列 - 图20

官方代码

  1. class Solution {
  2. public static boolean verifyPostorder(int[] postorder) {
  3. // postorder数组、区间范围[0,postorder.length - 1] 下限、上限
  4. return verifyPostorder(postorder, 0, postorder.length - 1,Integer.MIN_VALUE, Integer.MAX_VALUE);
  5. }
  6. private static boolean verifyPostorder(int[] postorder, int start, int end, int lowerlimit,int toplimit) {
  7. if (start > end) return true;
  8. // 根 大于上限、小于下限 则说明非法
  9. if (postorder[end] > toplimit || postorder[end] < lowerlimit) return false;
  10. // 左右子树是否合法由左右子树自己判断,根只判断自己结点是合法的
  11. // 因为没必要帮孩子判断他们是否合法,因为越下去上下限是越严格的
  12. for (int i = start; i <= end; i++) {
  13. // 找到第一个大于根节点的值,划分左右子树
  14. if (postorder[i] > postorder[end]) {
  15. // 左子树
  16. boolean left = verifyPostorder(postorder, start, i - 1, lowerlimit, postorder[end]);
  17. // 右子树
  18. boolean right = verifyPostorder(postorder, i, end - 1, postorder[end], toplimit);
  19. return left && right;
  20. }
  21. }
  22. // 说明没有右子树,只有左子树
  23. return verifyPostorder(postorder, start, end - 1, lowerlimit, postorder[end]);
  24. }
  25. }