剑指 offer33:二叉搜索树的后序遍历序列

本文详细介绍了如何验证一个给定的序列是否为二叉搜索树的后序遍历结果,分别提供了递归和栈两种解决方案。递归方法通过划分序列两部分,确保左子树所有元素小于根节点,右子树所有元素大于等于根节点。栈方法则利用后序遍历的特性,保证右子树的节点始终大于等于栈顶元素。这两种方法的时间复杂度分别为O(nlogn)和O(n),空间复杂度分别为O(nlogn)和O(n)。
摘要由CSDN通过智能技术生成

剑指 offer 33:二叉搜索树的后序遍历序列

在这里插入图片描述

二叉搜索树

二叉搜索树是一种节点值之间具有一定数量级次序的二叉树,对于树中的每个节点:

  • 如果其左子树存在,则左子树中每个节点的值都不大于该节点的值
  • 如果其右子树存在,则右子树中每个节点的值都不小于该节点的值
    示例
    在这里插入图片描述

递归

数组最后一个元素一定是根节点,根节点可以把前面的元素分成两组,从某一个元素之前的所有元素都不大于根节点的值,某一个元素到根节点位置都不小于根节点的值,否则就不是二叉搜索树的后序遍历序列,递归判断两个子部分,即不大于根节点的前半部分和不小于根节点的后半部分。

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        //二叉树节点个数小于等于 1
        if(postorder.length<=1){
            return true;
        }
        return verify(postorder,0,postorder.length-1);
        

    }
    private boolean verify(int[] postorder,int left,int right){
        //只有一个节点,返回 true
        if(left>=right){
            return true;
        }
        int mid=right;
        for(int i=left;i<right;i++){
            if(postorder[i]>=postorder[right]){
                mid = i;
                break;
            }
        }
        //判断右子树的节点是否都大于等于根节点
        for(int i= mid+1;i<right;i++){
            if(postorder[i]<postorder[right]){
                return false;
            }
        }

        return verify(postorder,left,mid-1) && verify(postorder,mid,right-1);
    }
}

在这里插入图片描述
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),递归栈占用的空间。

后序遍历的倒序(根右左),栈顶元素大于遍历值直接将元素添加到栈中,保证了右子树的正确,此时判断左子树是不是都小于 root 就可以了。
如果栈为空就把当前元素压栈。如果栈不为空,并且当前元素大于栈顶元素,说明是升序(右子树),那么说明当前元素是栈顶元素的右子节点,把当前元素压栈,如果一直升序,就一直压栈。当前元素小于栈顶元素,说明当前元素是某个节点的左子节点,我们要找到这个左子节点的父节点,就让栈顶元素出栈,直到栈为空或者栈顶元素小于当前值为止,其中最后一个出栈的就是当前元素的父节点(再进入循环时,就是当前父节点的左子树进栈,要判断左子树的节点是否小于根节点,如果不是返回 false)。
这种方法比较绕!

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        Stack<Integer> s = new Stack<>();
        int root = Integer.MAX_VALUE;
        for(int i=postorder.length-1;i>=0;i--){
            if(postorder[i]>root){
                return false;
            }
            while(!s.empty() && s.peek()>postorder[i]){
                root = s.pop();
            }
            s.push(postorder[i]);
        }
        return true;

    }
}

在这里插入图片描述
时间复杂度是 O ( n ) O(n) O(n),postorder 中的所有节点进栈出栈一次,使用 O ( n ) O(n) O(n)的时间。
空间复杂度 O ( n ) O(n) O(n),最差情况下,单调栈存储所有节点,使用 O ( n ) O(n) O(n)额外空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值