二叉树20:二叉搜索树的后序遍历序列

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路:输入一个整数数组,判断该数组是否是某个二叉搜索树的后序遍历的结果,关键找出搜索二叉树后序遍历的特点。对于上面的搜索二叉树,中序遍历的结果是①②③④⑤⑥⑦,后序遍历的结果是①③②⑤⑦⑥④,发掘搜索二叉树的后序遍历的特点是:数组的最后一个元素val是根结点,前面的元素分成2部分,开始的部分小于(题目规定没有相同的值)val,剩余的部分大于val,将其细分为[begin,index)是小于val的,[index,last)是大于val的,此外对于[begin,index)和[index,last)也对应2棵子树,要使得其为搜索二叉树也要满足最后一个结点是根结点val,且前面部分是小于val的,接着的部分是大于val的,这显然是一个递归的过程,一个数组[a,b]要符合搜索二叉树的要求,要求它的2个子数组也是搜索二叉树,并且整个数组满足前面的小于val后面的大于val,这是一个先判断条件再左子树再右子树的先序递归过程(其实后序遍历也可以,即先判断子数组再判断整个数组)。

设计一个递归函数来解决问题:输入数组和当前检查的数组的区间begin~end,判断这个区间的数组是否符合搜索二叉树后序遍历的要求,返回true或者false。题目的关键是找到这个区间中val左右子树的分界点,采用的方法是:先得到val,遍历数组区间[begin,end-1],找到第一个大于val的数,记录此时的下标为i,然后从j=i+1接着遍历直到end-1],如果出现j<val,说明这个数组不满足要求,return false,不用进行下面的子数组遍历;如果符合要求,那么i就是子数组的分界,2个子树组是[begin,i)和[i,end),如果遍历数组区间[begin,end-1]循环结束i=end-1,说明区间里面没有大于val的数,即val没有右子树,此时的右子数组为[end-1,end-1],表示空子树,已知空子树为搜索二叉树,因此让其返回true。

综上:对于一个区间[begin,end]判断是否是搜索二叉树:

①取int val=arr[end];

②i从[begin,end-1]开始遍历区间,直到找到一个大于val的元素break或者循环结束,此时的i是第一个大于val的元素或者是end,于是构建2个子数组是[begin,i-1]和[i,end-1].对这2个子数组再调用递归方法即可。

注意:上面有2个特殊情况,当begin<i-1即左子树为null,于是数组第一个元素就大于val,于是i=begin,显然begin>i-1,即begin>end或者i<end-1即右子树为null,于是当[begin,end-1]所有元素都遍历完成后都没有找到大于val的元素,于是此时i=end,于是i>end-1,即begin>end。

边界条件:递归判断一个数组[a,b]是否是搜索二叉树,终止条件就是某侧的子树为null,于是当遇到begin<i-1或者i<end-1就return结束递归即可,即边界条件是:begin>end。

注意:如果整棵二叉树都为null那么不是搜素二叉树,如果仅仅是某个子树为null,那么把它当做搜索树。

//判断一个数组是否是某搜索二叉树的后序遍历,递归,先判断再分解
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
 //特殊输入:如果整棵树都是空树那么不是搜索二叉树,如果只有部分子树为空那么可以是搜索二叉树
        if(sequence.length==0) return false;
        //调用递归方法解决问题
        return this.process(sequence,0,sequence.length-1);
    }
    
    //递归方法,输入一个数组和判断的区间,判断是否是一棵搜索二叉树
    private boolean process(int[] arr,int begin,int end){
        //边界条件
        if(begin>end) return true;
        //取最后一个元素作为分界值
        int val=arr[end];
        //①先判断整个数组是否符合大小关系
        int i=begin;
        for(;i<=end-1;i++){
            if(arr[i]>val) break;
        }
        for(int j=i+1;j<=end-1;j++){
            if(arr[j]<val) return false;
        }
        //此时i是2个子数组的分界点
        boolean b1=this.process(arr,begin,i-1);
        boolean b2=this.process(arr,i,end-1);
        return b1&&b2;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值