14 判断给定的二叉排序树后序遍历序列是否合法

前言

本博文部分图片, 思路来自于剑指offer 或者编程珠玑

问题描述

这里写图片描述

思路

对于这个问题, 书中给出了一种解法

思路 : 输入为一个后序遍历的序列, 从这里 我们可以得到序列中最后一个元素为根节点, 又因为该树是二叉排序树, 则表明序列中左子树的每一个结点的key小于等于根节点的key, 右子树的部分每一个结点的key大于等于根节点的key, so 我们是可以根据后序遍历序列大致区分出整棵树的左子树部分, 右子树部分 [不能确定的部分为和根节点关键字相同的结点], 这样就可以根据二叉排序树的性质进行校验了

首先 找到序列中第一个比最后一个key大的元素[索引即为idx], 然后在校验arr[idx] - arr[end-1]之间的数据, 是否都大于arr[end], 如果不全小于arr[end] 则返回false
     否则 便通过了初步的筛选, 然后进行递归校验左右子树, 如果左右子树任意一个不符合结点 返回false, 都通过了, 当前后序遍历序列才是正常的二叉排序树后序遍历序列

参考代码

/**
 * file name : Test07IsBinarySortedTreeEpilogue.java
 * created at : 2:48:59 PM Jun 7, 2015
 * created by 970655147
 */

package com.hx.test05;

public class Test07IsBinarySortedTreeEpilogue {

    // 判断给定的序列是否是二叉排序树的后序序列
    public static void main(String []args) {

//      int[] arr = new int[] {5, 7, 1, 9, 11, 10, 8 };
        int[] arr = new int[] {6, 11, 19, 27, 17, 37, 48, 38, 32 };
//      int[] arr = new int[] {6, 11, 17, 19, 27, 22, 48, 18, 37, 48, 38, 32 };

        boolean isLegal = isBinarySortedTreeEpilogue(arr, 0, arr.length-1);

        Log.log(isLegal);

    }

    // 注意 : start, end 包头包尾
    // 思路 : 如果只有一个 结点  直接返回true
        // 否则  从[start, end]找到    第一个大于arr[end]结点的数据的索引first, 然后校验[first, end)的数据  是否都大于end, 如果存在任意一个小于end, 直接返回false
        // 然后  校验左子树和右子树, 如果左子树的存在结点   递归校验左子树, 如果左子树校验返回false   直接返回false
            // 然后  校验右子树, 如果左右子树均校验通过   则 返回true
    public static boolean isBinarySortedTreeEpilogue(int[] arr, int start, int end) {
        if(arr == null) {
            return false;
        }
        if(start == end) {
            return true;
        }

        int first = findFirstBiggerThan(arr, start, end, arr[end]);

        // verify the seq since first which is bigger than root;
        for(int i=first; i<end; i++) {
            if(arr[i] < arr[end]) {
                return false;
            }
        }

        boolean isLeftLegal = true, isRightLegal = true;
        if(first > start) {
            isLeftLegal = isBinarySortedTreeEpilogue(arr, start, first-1);
            if(!isLeftLegal) {
                return false;
            }
        }
        if(first < end) {
            isRightLegal = isBinarySortedTreeEpilogue(arr, first, end-1);
        }

        return isLeftLegal && isRightLegal;
    }

    // 注意 : start, end 包头不包尾
    // 在[start, end)中  找到第一个大于tar的数据的索引
    private static int findFirstBiggerThan(int[] arr, int start, int end, int tar) {
        for(int i=start; i<end; i++) {
            if(arr[i] > tar) {
                return i;
            }
        }

        return end;
    }

}

效果截图

这里写图片描述

总结

因为二叉排序树 和后序遍历序列的性质很明显, 所以思路应该是不难, 时间复杂度为线性时间复杂度

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值