算法学习 day4--二叉搜索树的后序遍历序列

本题代码已上传到:gitbub

题目

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。
例如输入数组:{5,7,6,9,11,10,8},则返回true;{7,4,6,5},则返回false。

题目分析

本题需要对二叉搜索树及树的遍历的概念有一定的了解,先来看看这两个概念

  1. 二叉搜索树
    二叉搜索树有一个非常重要的性质:对于树中的每个节点X,它的左子树的所有节点的值小于X的值,它的右子树的所有节点的值大于X的值。这意味着,二叉搜索树可以按某种一致的方式排序。二叉树查找树的平均深度是 O(log N),非常适用于查找操作。
  2. 二叉树的遍历
    二叉树是一种类似链表的数据结构,在每个节点里存有其他节点(左右子节点)的引用。那么对二叉树的遍历,根据访问根节点是顺序,可以分为3种遍历方式:
    前序遍历:先访问根节点,再访问左节点,最后访问右节点;
    中序遍历:先访问左节点,再访问根节点,最后访问右节点;
    后序遍历:先访问左节点,再访问右节点,最后访问根节点;
    当然树还有许多其他的遍历方式,如层序遍历,但是因为并不常用,一般不讨论。

本题结合了这两个概念,因为二叉搜索树的性质,根据前序遍历序列或者后序遍历序列我们就可以重构一棵二叉搜索树了。而普通二叉树需要前序或后序,再配合中序,才能重构二叉树。对于本题我们只需要判断不需要重构,数组的最后一个元素即是根,数组前面的元素可以分为左子树和右子树,左子树的值都比根的值小,右子树的值都比根的值大。然后再以此递归左右子树进行判断即可。
另外一般我们不讨论有重复值的情况,那会变得相当复杂。具体可参考《数据结构与算法分析》

核心代码实现

 /**
     * 判断输入数组是否是二叉树后序遍历序列
     *
     * @param seq   后序遍历序列
     * @param start 开始索引
     * @param end   结束索引
     * @return 判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同
     */
    private static boolean verifyBst(int[] seq, int start, int end) {
        if (seq == null || seq.length == 0) {
            return false;
        } else if (seq.length == 1) {
            return true;
        }

        int root = seq[end];

        //找到右子树的开始索引
        int i = start;
        while (seq[i] < root && i++ < end) {
        }

        //如果右子树中有小于根的值,则不是二叉搜索树
        int j = i;
        while (j < end - 1) {
            if(seq[j] < root){
                return false;
            }
            j++;
        }

        boolean left = true;
        if (i - 1 > start) {
            left = verifyBst(seq, start, i - 1);
        }

        boolean right = true;
        if (i < end - 1) {
            right = verifyBst(seq, i, end - 1);
        }

        return left && right;
    }

测试用例

 public static void main(String[] args) {

        //完全二叉树
        int[] seq = {4, 8, 6, 12, 16, 14, 10};
        test("t1", seq, seq.length, true);

        //普通二叉树
        int[] seq2 = {4, 6, 7, 5};
        test("t2", seq2, seq2.length, true);

        //只有左节点的二叉树
        int[] seq3 = {1, 2, 3, 4, 5};
        test("t3", seq3, seq3.length, true);

        //只有右节点的二叉树
        int[] seq4 = {5, 4, 3, 2, 1};
        test("t4", seq4, seq4.length, true);

        //只有一个节点的二叉树
        int[] seq5 = {5};
        test("t5", seq5, seq5.length, true);

        //非二叉树
        int[] seq6 = {7, 4, 6, 5};
        test("t6", seq6, seq6.length, false);

        //非二叉树
        int[] seq7 = {4, 6, 12, 8, 16, 14, 10};
        test("t7", seq7, seq7.length, false
        );

        //空指针
        test("t5", null, 0, false);
    }
    
    private static void test(String test, int[] seq, int length, boolean expected) {
        boolean result = verifyBst(seq, 0, length - 1);
        System.out.print(test + " result : " + result + " ");
        if (result == expected) {
            System.out.println("passed.");
        } else {
            System.out.println("failed.");
        }
    }

测试结果

t1 result : true passed.
t2 result : true passed.
t3 result : true passed.
t4 result : true passed.
t5 result : true passed.
t6 result : false passed.
t7 result : false passed.
t5 result : false passed.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值