剑指Offer-二叉搜索树的后序遍历序列

题目描述

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

题目解析

刚开始看这道题目的时候,比较蒙,大概是因为我一开始就直接看代码,没看到什么细节性质的提示。再读了下题目,基本明白了他的意思,主要意思就是说给你一个序列,你确认下这个序列到底是不是一个二叉搜索树的后序遍历结果。这里稍微讲下,二叉搜索树的概念:根节点为参考,比根节点大的数据在右侧,比根节点小的数据在左侧,叶子节点左子节点比父节点小,右子节点比父节点要大。

解题思路

这个题目属于二叉搜索树的一个性质的考察,懂得什么是二叉搜索树的话才可以顺利进行,否则,概念都不懂根本搞不清楚哪里作为判断的标准。我觉得这个题目而言,找到判定标准很重要的,这应该说是一个决定本题能不能真正求出的关键,那么,我给出的建议是读者在自己思考时辅助举例子的方式进行,自己测试下,根据自己定义的一个二叉搜索树得到他的后续遍历序列,然后逆向推他到底是不是一个二叉搜索树的后续遍历的结果串。

这里以4,8,6,12,16,14,10为例子,首先,根节点10,这是可以直接得到的,那么根据其性质,根节点左侧的小于10,根节点右侧的大于10,那么可以将本题中的序列,切分为两个子集,切分为子集,一般的方式可以采用递归了,因为子集和其本身都是一个集合的抽象,将子集和全集视为一个类型的对象就可以了。注意这里当切分完成后需要进行一个检查,这个检查就是:第一个大于10的后面的这些序列中必须全部大于10,否则直接返回false。再看看左侧子集,左侧子集的话主要是4,8,6这个三个,然后将其视为新的全集进行上述操作,那么将6作为新的根节点,那么6而言,将4,8切分为两个子集,然后子集内进行上面的操作。


代码实现

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        
        if(sequence == null || sequence.length == 0) {
			return false;
		}
        
        if(sequence.length == 1) 
        	return true;
        
        int endNum = sequence[sequence.length - 1];
        
        int i = 0;
       	
        for(; i < sequence.length - 1; i ++) {
            
            if(sequence[i] > endNum) {
                break;
            }
        }
        int index = i;
        for(; index < sequence.length - 1; index++) {
        	
        	if(sequence[index] < endNum) {
        		return false;
        	}
        }
        
        int[] smaller = null;
        int[] bigger = null;
        
        smaller = new int[i];
        bigger = new int[sequence.length- i - 1];
        
        int in = 0;
        for(int j = 0; j < sequence.length - 1; j ++) {
        
        	if(j < i) {
            	smaller[j] = sequence[j];
        	} else {
            	bigger[in ++] = sequence[j];
        	}
    	}
        
        if(i == 0) {
        	
            return VerifySquenceOfBST(bigger);
            
        } else if(i == sequence.length - 1) {
            
            return VerifySquenceOfBST(smaller);
        } else {
        	
            return VerifySquenceOfBST(bigger) && VerifySquenceOfBST(smaller);
        }
        
    }
}
这个题还有优化的可能,比如上面的检查可以和查找比他大的数的index同时来进行,但是时间上并不会得到客观的提升,都是O(n),无非是代码减少了,下面是按照几个特例划分了左侧递归,右侧子集的递归,左侧和右侧都进行递归。
需要注意为空的情况,这是一个特例。其实我感觉这个特例不需要设计的,要么就在题目中说明。不过真正的项目中这个确实是要你自己去考虑到的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值