剑指offer第二版——面试题33(java)

面试题33:二叉搜索树的后序遍历序列

题目:

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果,如果是返回true,不是返回false。

假设输入的数组任意两个数字互不相同。

思路:

首先。。。我忘了啥是二叉搜索树了囧

二叉搜索树:二叉树,且所有的子树都满足左小右大

百度百科:

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

算法思路:

后序遍历可知,对每颗树,在后序遍历中,都是其根节点在最后,如P180(第二版)中的树,如果只有1层和2层,则后序遍历是6-10-8,可见对二叉搜索树来说,其后序遍历都可由根节点,将其分为两个部分,一部分全比根节点小,另一部分全比根节点大。再对两个部分迭代进行判断。

举例说明:

如题目中所举的例子,{5,7,6,9,11,10,8}

① 8为根节点,可分为5,7,6 和9,11,10两个部分,对两个部分再进行判断

② 5-7-6部分,6为根节点,可分为5和7两部分,由于其都无子结点,不再进行迭代;对9-11-10部分,可分为9和11两个部分,同理不再进行迭代

所以该例子是满足条件的

另一例子{7,4,6,5},根节点为5,7-4-6无法划分,所以不为二叉搜索树的后序遍历序列

代码:

public class Q33 {
    public static void main(String[] args) {
        int[] a = new int[] {5,7,6,9,11,10,8};
        int[] b = new int[] {7,4,6,5};
        int[] c = new int[] {9,2,5};
        System.out.println(tellBinarySearch(c));
	}
	
    public static boolean tellBinarySearch(int[] a) {
        if(a.length<2) {
            return true;
        }
        return tell(a, 0, a.length-1);
    }
	
    public static boolean tell(int[] a, int start, int end) {
        if(start == end) {
            return true;
        }
		
        // 找到分割数组的点
        int n = a[end];
		
        int left = start;
        while(left<=end && a[left]<n) {
            left++;
        }
		
        int right = end-1;
        while(right>=0 && a[right]>n) {
            right--;
        }
		
        if(right+1!=left) {
            return false;
        }
		
        return tell(a, start, right) && tell(a, left, end-1);
    }
}
// 2019-05-06
public class Q33 {
	public static void main(String[] args) {
		int[] a = new int[] {8,12,17,16,15,10};
		int[] b = new int[] {7,4,6,5};
		int[] c = new int[] {9,2,5};
		boolean r = tellBinarySearch(c);
		System.out.println(r);

	}
	
	public static boolean tellBinarySearch(int[] a) {
		// 最开始为空,返回假
		if(a.length==0) {
			return false;
		}
		
		// 数组只有一个值,为根节点,返回真
		if(a.length==1||a.length==2) {
			return true;
		}
		
		// 数组长度大于2的情况
		boolean left_,right_;
				
		int loc = findLoc(a);
		
		if(loc==-1) {
			return false;
		}

		left_ = tellBinarySearch(Arrays.copyOfRange(a, 0, loc+1));
		right_ = tellBinarySearch(Arrays.copyOfRange(a, loc+1, a.length-1));
		
		return left_&right_;
	}
	
	// 对大于2的数组进行查找划分点
	public static int findLoc(int[] a) {

		int left = 0;
		int right = a.length-1;
		int end = a[right--];
		
		while(a[right]>end) {
			right--;
		}
		
		while(a[left]<end) {
			left++;
		}
		
		if(right+1==left) {
			return right;
		}
		
		return -1;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值