剑指 Offer 33. 二叉搜索树的后序遍历序列

题目描述:

      输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
在这里插入图片描述
示例1:
输入: [1,6,3,2,5]
输出: false

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

解题思路:

1、递归:
     二叉搜索树的特点是节点数值的大小顺序是:left<root<right,而后序遍历的顺序是“左-右-根”,因此对一个二叉树来说,数组的最后一个数值是根节点,然后根据二叉搜索树的特点,遍历数组后可以得到左右子树的后序节点,这样通过递归地不断判断左右子树可以得出该数组是否满足某一个二叉搜索树的后序遍历。
注意点:递归的终止条件是i>=j,而不是i==j(这样当子树只有两个节点,即[1,2]时会出现问题)

2、单调栈:
     由于二叉搜索树的特点是节点数值的大小顺序是:left<root<right,而后序遍历的顺序是:left->right->root,这样不具有单调性,而反转后序遍历的顺序恰好是:root->right->left,这样对于每一个子树来说,从根节点到右孩子的数值都具有递增的性质。

     这里可以使用一个单调栈来保存递增的节点,当第一次将所有递增节点保存到栈后,这样这个子树的右节点以及右节点的右节点都保存到了栈中;当栈顶元素大于当前元素后,则循环弹出栈中元素,直至栈顶元素不大于当前元素后,这个时候后面子树的根节点更新为栈顶元素,然后将当前结点存入栈中。因为后面元素都是根节点的左子树或者左子树的孩子节点,因此后面元素不能大于根节点的数字,否则就不符合某二叉搜索树的后序遍历结果。这个二叉搜索树可以初始化看成一个根节点数值为Integer.MAX_VALUE的左子树。

实现代码:

	//解法1:递归
    public boolean verifyPostorder(int[] postorder) {
        return recur(postorder, 0, postorder.length - 1);
    }

    public boolean recur(int[] postorder, int i, int j){
        if(i >= j)//这里不能只写==,这样会出现数组越界错误
            return true;
        int m = i;
        while(postorder[m] < postorder[j])
            m++;
        int p = m;
        while(postorder[p] > postorder[j])
            p++;
        return p == j && recur(postorder, i, m - 1) && recur(postorder, m, j - 1);
    }


   //解法2:单调栈
    public boolean verifyPostorder1(int[] postorder) {
        Stack<Integer> stack = new Stack<>();
        int root = Integer.MAX_VALUE;
        for(int i = postorder.length - 1; i >= 0; i--){
            if(postorder[i] > root)
                return false;
            while(!stack.empty() && stack.peek() > postorder[i])
                root = stack.pop();//更新root
            stack.add(postorder[i]);
        }
        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值