考点:二叉搜索树、后序遍历
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。如数组{5,7,6,9,11,10,8}是如下二叉树的后序遍历,是二叉搜索树。
知识点复习
1.特殊二叉树:
(1)满二叉树:二叉树中,所有分支都有左右孩子,且叶子节点在同一层
(2)完全二叉树:编号为i的节点与满二叉树编号同样为i的节点位置相同
特点:
- 叶子节点只出现在最下两层
- 最下层叶子节点在左部,倒数第二次叶子节点在右部
- 不存在只有右子树情况
(3)二叉搜索树(二叉查找树、二叉排序树): 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
2.二叉树遍历:
前序:根左右
中序:左根右
后序:左右根
本题分析思路
在后序遍历中,最后一个数字是树的根节点。数组前面的数字,第一部分是左子树节点,都比根节点小;第二部分是右子树节点,都比根节点大。突破点先确定根节点,通过遍历比root小的值确定左部分;剩下右部分中,一旦有小于root,则不是二叉搜索树。递归判断左右子树。
实现代码
public:
bool VerifySquenceOfBST(vector<int> sequence) {
return bst(sequence,0,sequence.size()-1);
}
private:
bool bst(vector<int> seq,int begin,int end){
if(seq.empty()||begin>end)
return false;
int root=seq[end]; //后序遍历最后一个数必是根节点
int i=begin;
//遍历左孩子值都小于root
for(;i<end;i++){
if(seq[i]>root)
break;
}
//一旦有大于root的值开始遍历右孩子(j从i开始)
int j=i;
for(;j<end;j++){
if(seq[j]<root)
return false;
}
bool left=true;
bool right=true;
//左右递归
if(i-1>begin)
left= bst(seq,begin,i-1);
if(i<end-1)
right=bst(seq,i,end-1);
return left&&right;
}
方法2
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.empty())
return false;
return bst(sequence,0,sequence.size()-1);
}
bool bst(vector<int> seq,int begin,int end){
//递归结束条件(到最底层)
if(begin >=end)
return true;
int root=seq[end];
int i=begin;
for(;i<end;i++){
if(seq[i]>root)
break;
}
int j=i;
for(;j<end;j++){
if(seq[j]<root)
return false;
}
return bst(seq,begin,i-1) && bst(seq,i,end-1);
}