题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出true,否则输出false。假设输入的数组的任意两个数字都互不相同。
思路:
1.在后序遍历序列中,最后一个数字是树的根节点的值。数组中前面的数字可以分为两部分:第一部分是左子树节点的值,它们都比根节点的值小;第二部分是右子树节点的值,它们都比根节点的值大。
2.所以先取数组中最后一个数,作为根节点。然后从数组开始计数比根节点小的数,并将这些记作左子树,然后判断后序的树是否比根节点大,如果有点不满足,则跳出,并判断为不成立。全满足的话,依次对左子树和右子树递归判断。
java参考代码如下:
package chapter4;
public class P179_SequenceOfBST {
public static boolean verifySquenceOfBST(int[] data){
//空树
if(data==null||data.length==0)
return false;
return verifySquenceOfBST(data,0,data.length-1);
}
public static boolean verifySquenceOfBST(int[] data,int start,int end){
//数组长度为2,一定能够组成BST
if(end-start<=1)
return true;
//根节点的值
int root = data[end];
// 在二叉搜索树中左子树节点的值小于根节点的值
int i=start;
for(;i<=end-1;i++){
if(data[i]>root)//在右子树的第一个节点跳出
break;
}
// 在二叉搜索树中右子树节点的值大于根节点的值
int j=i;
for(;j<end;j++){
if(data[j]<root)
return false;
}
//判断左右子树是不是二叉搜索树
return verifySquenceOfBST(data,start,i-1)&&verifySquenceOfBST(data,i+1,end);
}
public static void main(String[] args){
// 8
// / \
// 6 10
// / \ / \
// 5 7 9 11
int[] data = {5,7,6,9,11,10,8};
int[] data1={7,4,6,5};
System.out.println(verifySquenceOfBST(data));
System.out.println(verifySquenceOfBST(data1));
}
}
参考处二叉搜索树的后序遍历序列
基于以上思路,C++参考代码如下:
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
if(!sequence.size())
return false;
return judge(sequence,0,sequence.size()-1);
}
bool judge(vector<int> &a,int l,int r) //l为左边界 r 为右边界
{
if(l>=r) return true;
/*比如1 4 3 5这个二叉搜索树的后序遍历,没有右子树,
所以r一直对应的是4这个索引,当return judge(a, l, i - 1) && (judge(a, i, r - 1))中的第二个递归
i=r,r-1<r,所以应该是返回true
l==r对应的是叶子结点,l>r对应的是空树,这两种情况都是true
*/
int i=r;
while(i>l&&a[i-1]>a[r]) //i 一直移动 移动到左子树边界 判定条件即右子树所有节点都需要大于根节点
--i;
for(int j=i-1;j>=l;--j) //j为i-1即相对于根节点的左子树,遍历左子树 如果左子树中有任何一个节点大于根节点 return false
{
if(a[j]>a[r])
{
return false;
}
}
return judge(a,l,i-1)&&judge(a,i,r-1);
}
};
测试用例:
a.功能测试(输入的后序遍历序列对应一颗二叉树,包括完全二叉树、所有节点都没有左/右子树的二叉树、只有一个节点的二叉树;输入的后序遍历序列没有对应一颗二叉树)。
b.特殊输入测试(指向后序遍历序列的指针为nullptr指针)。
参考:
https://blog.csdn.net/Heloiselt/article/details/80227473
https://www.jianshu.com/p/49aaf6e0491d