要求:判断是否为一个后序
思路:
法一:最后一个为根,因为二叉搜索树根右边所有都大于它,所以从前找到第一个大于根的以此划分左右子树,递归。如果在右子根往后找到一个比根小的那么返回false
class Solution {
public:
bool dfs(int start,int end,vector<int>& postorder){
if(start>=end)return true;
int rootval=postorder[end];
int rroot=start;
while(rroot<end&&postorder[rroot]<rootval)++rroot;
for(int i=rroot;i<end;++i)
if(postorder[i]<rootval)return false;
return dfs(start,rroot-1,postorder)&&dfs(rroot,end-1,postorder);
}
bool verifyPostorder(vector<int>& postorder) {
return dfs(0,postorder.size()-1,postorder);
}
};
法二:栈。后序是左右中,我们反过来,根右左,由bst性质知道根-右是单调递增的。我们一直压栈根-右,为递增栈。如果当前值大于栈顶,也就是根右左已经进行到左了,我们为了继续模拟遍历根右左过程,需要回到孩子没遍历完的根,如下图所示,到6时我们下一个要访问的是3,所以栈要弹出直到5小于当前值6,5留下因为左子树还没完。为什么是5而不是8?因为8比6大,根据bst性质,大于的在右边,我们根右左已经遍历了右边,所以要找一个小的,在左边,其左子树肯定没访问。出错条件是后面有比8大的因为8已经访问完了
综上所述,如果当前值大于栈顶则加栈,小于的话弹出直到当前值大于栈顶,用pre记录之前弹出的8然后加入当前值
如果下一个大于pre那么出错
5
3 8
1 4 6 9
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
stack<int> s;
int n=postorder.size();
int pre=0x7fffffff;
for(int i=n-1;i>=0;--i){
if(postorder[i]>pre)return false;
while(!s.empty()&&s.top()>postorder[i]){
pre=s.top();
s.pop();
}
s.push(postorder[i]);
}
return true;
}
};