剑指 Offer 33. 二叉搜索树的后序遍历序列 - 力扣(LeetCode)
对于任意一颗树,根节点总是后序遍历中的最后一个节点,后序遍历的形式总是:
[ [左子树的后序遍历结果], [右子树的后序遍历结果], 根节点 ]
所以划分点就是第一个大于根节点的元素,第一个区间内的元素必然全部小于根节点,第二个区间的元素必然全部大于根节点。
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
int n = postorder.size();
if(n <= 2) return true;
return isOk(postorder, 0, n-1);
}
bool isOk(vector<int> &a, int l, int r){
if(r-l <= 2) return true;//元素小于等于两个
int idx = 0;
while(idx < r && a[idx] < a[r]) ++idx;
if(idx == r) return isOk(a, l, r-1);
else{//检查区间内元素是否符合要求
for(int i = idx+1; i <= r-1; ++i){//idx -- r-1之间的元素必须全部大于a[r]
if(a[i] < a[r]) return false;
}
}
return isOk(a, l, idx-1) && isOk(a, idx, r-1);
}
};
看题解发现还有一个单调栈的思路:单调递增栈辅助,逆向遍历数组 - 二叉搜索树的后序遍历序列 - 力扣(LeetCode)
真的用的很巧妙
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
stack<int> s;
int pre = INT_MAX;//表示上一个根节点
for(int i = postorder.size()-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;
}
};