剑指offer—二叉搜索树的后序遍历序列
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5
/ \
2 6
/ \
1 3
示例 1:
输入: [1,6,3,2,5]
输出: false
示例 2:
输入: [1,3,2,6,5]
输出: true
思路
二叉搜索树特点:左子树比当前值小,右子树比当前值大;即左子树的全部结点都比当前值小,右子树的所有结点都比当前值大
后序遍历(LRD):
[
左
子
树
\color{red}{[左子树}
[左子树|
右
子
树
\color{red} {右子树}
右子树|
根
节
点
]
\color{red}{根节点]}
根节点]
递归:
1:终止条件:if(start >= end) return true
2:根据当前范围的根节点,划分左右子树,左子树的值都比当前根节点要小,右子树的值都比当前根节点要大
3:因为第2步划分时验证了左子树,那么接下来根据划分的右子树验证是否都比根节点要大
4:递归判断左右子树
代码
bool isPostorder(vector<int>& postorder, int start, int end){
//递归终止条件
if(start >= end) return true;
//找到左子树和右子树的划分点
int i = start;
while(postorder[i] < postorder[end]){
i++;
}
int bound = i;
//遍历右子树,判断是否都比根节点大
for(; i < end; i++){
if(postorder[i] < postorder[end]) return false;
}
//递归遍历左右子树
return isPostorder(postorder, start, bound-1) && isPostorder(postorder, bound, end-1);
}
bool verifyPostorder(vector<int>& postorder) {
int n = postorder.size();
if(n == 1) return true;
if(n == 2) return postorder[0]>postorder[1];
return isPostorder(postorder, 0, n-1);
}
复杂度分析
时间复杂度: O ( N 2 ) O(N^2) O(N2)
当树退化成链表,每一次递归,都需要遍历树的所有结点,占用 O ( N ) O(N) O(N)
空间复杂度: O ( N ) O(N) O(N)
最差情况下(即当树退化为链表),递归深度将达到 N N N