1、题目描述
2、解题思路
二叉搜索树的前序遍历特点是整体递增,局部递减。
先把根节点 preorder[0] 入栈 stack。
定义一个变量 min 表示递减序列的第一个值,初始为负无穷。
接着遍历 preorder[] 的 1 到最后一个数字。
1、如果 preorder[i] < stack.peek(),说明还处于递减状态,stack.push(preorder[i]);
2、如果 preorder[i] > stack.peek(),说明递减状态结束了,从 i 开始就要递增了,也就是某个节点的左子节点结束了,i 是它的右子节点,我们不断 stack.pop(),直到遇到一个数字,preorder[i] 小于它,那它就是 preorder[i] 的父结点,preorder[i] 是它的右子节点。更新 min 为 stack 最后弹出去的元素,即递减序列的第一个数字。
3、我们知道 min 表示上一个递减序列的第一个值,如果在后面遇到 preorder[i] < min,说明 preorder 不是前序遍历。看下图即可理解:
这个 1 如果按照二叉搜索树的特点,应该在 2 的左子节点中。如果按照 preorder 顺序,它又在 6 后面。前后矛盾。
3、解题代码
class Solution {
public boolean verifyPreorder(int[] preorder) {
if (preorder.length <= 2) return true;
Stack<Integer> stack = new Stack<>();
stack.push(preorder[0]);
int min = Integer.MIN_VALUE;
for (int i = 1; i < preorder.length; i++) {
if (preorder[i] < min) return false;
if (stack.peek() > preorder[i]) {
// 处于左子树递减序列
stack.push(preorder[i]);
} else {
// <
// 把比 preorder[i] 大的数字弹出去
while (!stack.isEmpty() && preorder[i] > stack.peek()) {
min = stack.pop();
}
stack.push(preorder[i]);
// 现在 preorder[i] 只能是 min 的右子节点
}
}
return true;
}
}