问题
思路
这个题目我觉得还是不错的,自己起初没有想出来。
其实主要是要结合后续遍历的思路,序列中最后一个节点一定是根。然后此时,考虑BST的性质,左子树比根小,右子树比根大。所以前面的序列也是一部分比根小,一部分比根大。并且这两个序列都是完全连续的。
这题另外一个总要思路就是对于树这种递归结构,最常见的解决办法是递归的方法。所以,一定要想到递归的思路,问题迎刃而解。这个题和知道前序和中序还原二叉树是一样的办法。
递归的思路是这样,原序列是BST的后序遍历当且仅当前面一部分序列是左子树后续遍历序列,右子树序列是后续遍历序列。
这两部分序列有一个前提条件就是,左子树全都比根小,右子树全都比根大。但是反之不成,但是尽管反之不成,这也是一个条件,即如果左子树中存在一个比根大,它一定不是合法的BST后续序列。右子树同理,所以这个题我们把矛盾放到右子树上面,只要找到第一个比根大的我就认为这是右子树开始的序列,那么前面的部分是左子树开始的序列。可以肯定的是,此时的左子树一定是满足全部小于根节点的,但是至于他到底是不是BST的后序遍历序列,还需要再判断。但是,此时右子树不一定满足全部比根大的条件,要先判断,判断完之后再进一部判断它是不是BST的后续遍历序列。
代码
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
int sz = sequence.size();
if(!sz) return false;
return helper(sequence, 0, sz-1);
}
private:
bool helper( const vector<int>& arr, int s, int t ){
if( s >= t )
return true;
else{
int root = arr[t];
int idx;
for(idx = 0; idx < t; ++idx){
if( arr[idx] > root )
break;
}// [s, idx - 1] - left
for(int j = idx + 1; j < t; ++j){
if( arr[j] <= root )
return false;
}// [idx, t-1] - right
return helper(arr, s, idx-1) && helper(arr, idx, t-1);
}
}
};