牛客解题思路:二叉搜索树的后序遍历序列

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


思路:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。

我们都知道二叉搜索树的中序遍历实际上就是排好序的,而二叉搜索树的后序遍历是无序的,那我们如何判断呢?->

首先我们知道二叉树的后序遍历中最后一个节点一定是根节点,那么我们知道了根节点之后,我们可以判断,除了这个根节点,其他的节点应该可以被分成两份,一份全部小于等于根节点,一份全部大于等于根节点,并且这两份还可以按照上述的方法继续划分。这就是一个递归的过程。->

当我们划分到无法再划分时,那么就可以断定该二叉树就是二叉搜索树了,当然,这有个前提,就是在递归遍历过程中没有返回false,因为递归的过程中还会穿插有相应的判断。->

也就是我们需要先统计除去根节点之外的序列中,节点值小于等于(这里是可以算上等于的对结果没有影响的(●ˇ∀ˇ●))该根节点值的节点的个数n,然后再顺序遍历除根节点外的序列是不是除前n个之后几个都大于根节点值(这一步非常重要!!!!确保此时除根结点的序列只能被划分为严格的两份!!!),若不是可以直接返回false无需再继续递归:

    int rootVal = sequence[last];
    int cutIndex = first;
    while (cutIndex < last && sequence[cutIndex] <= rootVal)
        cutIndex++;
    for (int i = cutIndex; i < last; i++)
        if (sequence[i] < rootVal)
            return false;

完整代码如下:

public boolean VerifySquenceOfBST(int[] sequence) {
    if (sequence == null || sequence.length == 0)
        return false;
    return verify(sequence, 0, sequence.length - 1);
}

public boolean verify(int[] sequence, int first, int last) {
    if (last - first <= 1)
        return true;
    int rootVal = sequence[last];
    int cutIndex = first;
    while (cutIndex < last && sequence[cutIndex] <= rootVal)
        cutIndex++;
    for (int i = cutIndex; i < last; i++)
        if (sequence[i] < rootVal)
            return false;
    return verify(sequence, first, cutIndex - 1) && verify(sequence, cutIndex, last - 1);
}

然而上面的方法还是比较常规的,这里提供一个新思路。前面有道题是“栈的压入、弹出序列”。写这道题的例子时发现二叉树的中序序列和后序序列就满足栈的压入弹出序列关系。即如果把中序序列当做栈的压入序列,那么后序序列是该栈的一个弹出序列。而BST的中序是排序数组。因此将本题的序列排序作为中序序列,引用前面题的答案判断两序列是否满足上述关系即可。
注意数组的克隆要用深拷贝clone()哦(✿◕‿◕✿):

public boolean VerifySquenceOfBST(int [] seq) {
    int[] arr = seq.clone();
    Arrays.sort(arr);
    return IsPopOrder(arr,seq);
     
}
//判断第二个序列是否可能为第一个序列的弹出顺序,引用的“栈的压入、弹出序列”题目的答案
public boolean IsPopOrder(int [] pushA,int [] popA) {
    if(pushA.length == 0 || popA.length == 0)
        return false;
    Stack<Integer> s = new Stack<Integer>();
    //用于标识弹出序列的位置
    int popIndex = 0;
    for(int i = 0; i< pushA.length;i++){
        s.push(pushA[i]);
        //如果栈不为空,且栈顶元素等于弹出序列
        while(!s.empty() &&s.peek() == popA[popIndex]){
            //出栈
            s.pop();
            //弹出序列向后一位
            popIndex++;
        }
    }
    return s.empty();
}

这个方法我认为还是存在一些问题的,只能证明x序列是不是中序遍历的一个弹出序列,并不能证明x序列是后续遍历序列,所以还是使用第一种方法吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值