您的位置:首页 > 理论基础 > 数据结构算法

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

2016-01-11 20:45 519 查看

前言

本博文部分图片, 思路来自于剑指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, 所以请大家指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 数据结构 java