《剑指offer》面试题33:二叉搜索树的后序遍历序列

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


思路:

1.在后序遍历序列中,最后一个数字是树的根节点的值。数组中前面的数字可以分为两部分:第一部分是左子树节点的值,它们都比根节点的值小;第二部分是右子树节点的值,它们都比根节点的值大。
2.所以先取数组中最后一个数,作为根节点。然后从数组开始计数比根节点小的数,并将这些记作左子树,然后判断后序的树是否比根节点大,如果有点不满足,则跳出,并判断为不成立。全满足的话,依次对左子树和右子树递归判断。

java参考代码如下:

package chapter4;

public class P179_SequenceOfBST {
    public static boolean verifySquenceOfBST(int[] data){
        //空树
        if(data==null||data.length==0)
            return false;
        return verifySquenceOfBST(data,0,data.length-1);
    }
    public static boolean verifySquenceOfBST(int[] data,int start,int end){
        //数组长度为2,一定能够组成BST
        if(end-start<=1)
            return true;
        //根节点的值
        int root = data[end];

        // 在二叉搜索树中左子树节点的值小于根节点的值
        int i=start;
        for(;i<=end-1;i++){
            if(data[i]>root)//在右子树的第一个节点跳出
                break;
        }

        // 在二叉搜索树中右子树节点的值大于根节点的值
        int j=i;
        for(;j<end;j++){
            if(data[j]<root)
                return false;
        }

        //判断左右子树是不是二叉搜索树
        return verifySquenceOfBST(data,start,i-1)&&verifySquenceOfBST(data,i+1,end);
    }
    public static void main(String[] args){
        //            8
        //          /   \
        //         6     10
        //       /  \   / \
        //      5    7 9   11
        int[] data = {5,7,6,9,11,10,8};
        int[] data1={7,4,6,5};
        System.out.println(verifySquenceOfBST(data));
        System.out.println(verifySquenceOfBST(data1));
    }
}

参考处二叉搜索树的后序遍历序列

基于以上思路,C++参考代码如下:

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(!sequence.size())
            return false;
        return judge(sequence,0,sequence.size()-1);
 
    }
    
    bool judge(vector<int> &a,int l,int r) //l为左边界 r 为右边界
    {
        if(l>=r) return true;
  
        /*比如1 4 3 5这个二叉搜索树的后序遍历,没有右子树,
        所以r一直对应的是4这个索引,当return judge(a, l, i - 1) && (judge(a, i, r - 1))中的第二个递归
        i=r,r-1<r,所以应该是返回true
        l==r对应的是叶子结点,l>r对应的是空树,这两种情况都是true
        */
        
        int i=r;
        while(i>l&&a[i-1]>a[r])    //i 一直移动 移动到左子树边界  判定条件即右子树所有节点都需要大于根节点
            --i;
        for(int j=i-1;j>=l;--j)    //j为i-1即相对于根节点的左子树,遍历左子树 如果左子树中有任何一个节点大于根节点 return false
        {
            if(a[j]>a[r])
            {
                return false;
            }
        }
        return judge(a,l,i-1)&&judge(a,i,r-1);
        
    }
};
测试用例:

a.功能测试(输入的后序遍历序列对应一颗二叉树,包括完全二叉树、所有节点都没有左/右子树的二叉树、只有一个节点的二叉树;输入的后序遍历序列没有对应一颗二叉树)。
b.特殊输入测试(指向后序遍历序列的指针为nullptr指针)。

参考:

https://blog.csdn.net/Heloiselt/article/details/80227473
https://www.jianshu.com/p/49aaf6e0491d

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值