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

来源:互联网 发布:caffe 自定义数据层 编辑:程序博客网 时间:2024/06/07 03:26

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出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
原创粉丝点击