#数据结构与算法学习笔记#剑指Offer22:判断是否二叉搜索树的后序遍历序列 + 测试用例(Java、C/C++)

版权声明:本文为博主NJU_ChopinXBP原创文章,发表于CSDN,仅供交流学习使用,转载请私信或评论联系,未经博主允许不得转载。感谢您的评论与点赞。 https://blog.csdn.net/qq_20304723/article/details/82083211

2018.8.26

这道题的思路是递归。对于一个二叉搜索树的后序遍历序列,最后一个输出的结点为根节点。由于二叉搜索树的左子树所有结点必小于根节点,右子树所有结点必大于根节点,因此序列的前一部分的结点值对应左子树结点值(如果存在左子树),后一部分的结点值对应右子树的结点值(如果存在右子树),分别小于与大于根节点值。

判定的条件也即如此,若右子树序列中有存在某一个结点值大于根节点值,则该序列不是二叉搜索树的后序遍历序列。因此只要每次根据子序列最后一个输出结点对应的根节点值,找出左右子树的分界点,将当前序列分割成左右子序列,不断递归进行判定即可。

当序列结点值小于等于两个时,不论顺序如何都有对应的后序遍历输出。


题目描述

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


Java实现:

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length == 0)return false;
    	int begin = 0;
        int end = sequence.length - 1;
        return Solution(sequence, begin, end);
    }
    
    public static boolean Solution(int [] seq, int begin, int end){
    	//若序列元素小于两个,必符合后序遍历
    	if(end - begin <= 1){
    		return true;
    	}
    	
		int root = seq[end]; // 序列尾结点为当前根节点,也是左右子树大小分隔值
		int edge = begin; // 用于记录左右子树分隔点,最终edge指向右子树根节点所在序列位置
		while (edge < end) {
			if (seq[edge] > root) break;	//确定分隔点所在序列位置
			edge++;
		}
		//若分隔点后有值小于分隔值,则不符合二叉搜索树后序遍历条件
		for(int i = edge; i < end; i++){
			if (seq[i] < root) return false;
		}
		return Solution(seq, begin, edge - 1) && Solution(seq, edge, end - 1);		
    }
}

C++实现示例(递归):

// BST:Binary Search Tree,二叉搜索树
bool VerifySquenceOfBST(int sequence[], int length)
{
    if(sequence == NULL || length <= 0)
        return false;

    int root = sequence[length - 1];

    // 在二叉搜索树中左子树的结点小于根结点
    int i = 0;
    for(; i < length - 1; ++ i)
    {
        if(sequence[i] > root)
            break;
    }

    // 在二叉搜索树中右子树的结点大于根结点
    int j = i;
    for(; j < length - 1; ++ j)
    {
        if(sequence[j] < root)
            return false;
    }

    // 判断左子树是不是二叉搜索树
    bool left = true;
    if(i > 0)
        left = VerifySquenceOfBST(sequence, i);

    // 判断右子树是不是二叉搜索树
    bool right = true;
    if(i < length - 1)
        right = VerifySquenceOfBST(sequence + i, length - i - 1);

    return (left && right);
}

C++实现示例(非递归):

//非递归 
//非递归也是一个基于递归的思想:
//左子树一定比右子树小,因此去掉根后,数字分为left,right两部分,right部分的
//最后一个数字是右子树的根他也比左子树所有值大,因此我们可以每次只看右子树是否符合条件即可,
//即使到达了左子树左子树也可以看出由左右子树组成的树还像右子树那样处理
 
//对于左子树回到了原问题,对于右子树,左子树的所有值都比右子树的根小可以暂时把他看出右子树的左子树
//只需看看右子树的右子树是否符合要求即可
class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        int size = sequence.size();
        if(0==size)return false;
 
        int i = 0;
        while(--size)
        {
            while(sequence[i]<sequence[size])i++;
            while(sequence[i]>sequence[size])i++;
 
            if(i<size)return false;
            i=0;
        }
        return true;
    }
};

测试代码:

// ====================测试代码====================
void Test(char* testName, int sequence[], int length, bool expected)
{
    if(testName != NULL)
        printf("%s begins: ", testName);

    if(VerifySquenceOfBST(sequence, length) == expected)
        printf("passed.\n");
    else
        printf("failed.\n");
}

//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16
void Test1()
{
    int data[] = {4, 8, 6, 12, 16, 14, 10};
    Test("Test1", data, sizeof(data)/sizeof(int), true);
}

//           5
//          / \
//         4   7
//            /
//           6
void Test2()
{
    int data[] = {4, 6, 7, 5};
    Test("Test2", data, sizeof(data)/sizeof(int), true);
}

//               5
//              /
//             4
//            /
//           3
//          /
//         2
//        /
//       1
void Test3()
{
    int data[] = {1, 2, 3, 4, 5};
    Test("Test3", data, sizeof(data)/sizeof(int), true);
}

// 1
//  \
//   2
//    \
//     3
//      \
//       4
//        \
//         5
void Test4()
{
    int data[] = {5, 4, 3, 2, 1};
    Test("Test4", data, sizeof(data)/sizeof(int), true);
}

// 树中只有1个结点
void Test5()
{
    int data[] = {5};
    Test("Test5", data, sizeof(data)/sizeof(int), true);
}

void Test6()
{
    int data[] = {7, 4, 6, 5};
    Test("Test6", data, sizeof(data)/sizeof(int), false);
}

void Test7()
{
    int data[] = {4, 6, 12, 8, 16, 14, 10};
    Test("Test7", data, sizeof(data)/sizeof(int), false);
}

void Test8()
{
    Test("Test8", NULL, 0, false);
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Test7();
    Test8();

    return 0;
}

#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/82083211