题目描述

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。

https://leetcode.cn/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/

题解

二叉搜索树:根节点的左子树节点都小于根节点;右子树节点都大于根节点。

后序遍历:左 | 右 | 根

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
bool verifyPostorder(vector<int>& postorder, int left, int right) {
if (left >= right) return true;
int root = postorder[right];
int mid = left;
while (mid < right && postorder[mid] < root) mid++;
for (int i = mid; i < right; i++) {
if (postorder[i] < root) return false;
}
return verifyPostorder(postorder, left, mid - 1)
&& verifyPostorder(postorder, mid, right - 1);
}
public:
bool verifyPostorder(vector<int>& postorder) {
return verifyPostorder(postorder, 0, postorder.size() - 1);
}
};

时间复杂度 O(N2)O(N^2):每次递归减去一个根节点,递归 O(N);最坏情况下,树退化为链表,每次递归都需要遍历剩余所有节点,O(N)。
空间复杂度 O(N)O(N):最差情况下,当树退化为链表,递归深度为 O(N)。

单调栈

后序遍历的逆序:根 | 右 | 左,其中 根 | 右 递增,依次入栈;

开始入栈时,比栈顶小,开始出栈,直到栈顶元素比将要入栈的元素小或栈为空;

最后一个出栈的即为根节点,后面入栈的节点都在根节点的左子树,应该都比记录的根节点小。

根节点初始值设为 INT_MAX。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
int n = postorder.size();
stack<int> stk;
int root = INT_MAX;
for (int i = n - 1; i >= 0; i--) {
if (postorder[i] > root) return false;
while (!stk.empty() && postorder[i] < stk.top()) {
root = stk.top(); stk.pop();
}
stk.push(postorder[i]);
}
return true;
}
};

时间复杂度 O(N)O(N):遍历 postorder 所有节点,各节点均入栈、出栈一次。
空间复杂度 O(N)O(N):最差情况下,单调栈 stack 存储所有节点。