力扣题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true
,否则返回 false
。假设输入的数组的任意两个数字都互不相同。
代码:
bool verifyPostorder(vector<int>& postorder) {
if(postorder.size()==0 || postorder.size()==1) return true;
stack<int> s;
int max = INT32_MIN;
s.push(postorder[postorder.size()-1]);
for(int i=postorder.size()-2;i>=0;i--){
if(postorder[i]>s.top()){ //单调栈,存放从小到大
s.push(postorder[i]);
}else{ //某个值小于栈顶部值,开始单出,直到能放入,并保留最后一个弹出值
while(s.size()!=0&&s.top()>postorder[i]){
//cout<<s.top()<<endl;
max = s.top();
s.pop();
}
// cout<<postorder[i]<<endl;
s.push(postorder[i]);
continue;
}
if(max == INT32_MIN){
continue;
}else{
if(s.size()==0) continue;
//cout<<max<<" "<<s.size()<<endl;
if(s.top()>max) return false;//后续插入值比弹出值大,则不符合后续遍历,直接false
}
}
return true;
}
思路:
来自力扣评论区的思路,后续遍历为左->右->中,将其反过来变为中->右->左,此时为方向相反的先序遍历,再根据二叉搜索树的性质,此时遍历先往右会遍历大值,之后往左遍历小值。
设立单调递增栈,当遍历到小于栈顶值时则表明开始遍历左子树,此时弹栈直到新值能入栈,并保留最后一个弹栈值,此时为了满足性质,该弹栈值便是此时子树的根,设为x(因为根据遍历性质,此时是在一直遍历右子树,当出现小于栈顶值即代表开始遍历左子树,而根据二叉搜索树性质,此时取弹出栈的数值中的最小值,该值大于准备入栈的值,而该值为了满足二叉树定义必定为根节点,使得之前入栈值位于右子树,准备入栈的值为左子树)。由于x为子树根,则之后新入栈值必定比x小,若比x大则不符合定义直接false。
之后不断重复上述操作,继续保持单调递增栈,当又出现小于栈顶值则再按照上述操作更新x,直到数组postorder遍历完毕即可返回true。