输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。(ps:我们约定空树不是二叉搜素树)
法1:递归
//二叉排序树,满足左子树所有节点<根节点<右子树所有节点
//同时,后续遍历最后一个节点为跟节点
//先取到根节点,然后根据大小关系划分左右子树节点,看看是否满足大小关系。
//递归的在左右子树节点上进行判断
public class Solution {
//二叉排序树,满足左子树所有节点<根节点<右子树所有节点
//同时,后续遍历最后一个节点为跟节点
//先取到根节点,然后根据大小关系划分左右子树节点,看看是否满足大小关系。
//递归的在左右子树节点上进行判断
public boolean VerifySquenceOfBST(int [] sequence) {
if(sequence==null||sequence.length<=0) return false;
return Is_BST(sequence,0,sequence.length-1);
}
public boolean Is_BST(int[] sequence,int start,int end){
if(start>=end) return true;
int pivot;
for(pivot=start;sequence[pivot]<sequence[end];pivot++);//划分左子树
for(int i=pivot;i<=end;i++){ //判断“右子树”是否满足条件
if(sequence[i]<sequence[end]) return false;
}
return Is_BST(sequence,start,pivot-1) && Is_BST(sequence,pivot,end-1);
}
}
法2:上限约束法 O(n)
https://blog.nowcoder.net/n/8fe97e67996249ccbe71328d3a49c4af?f=comment
BST树的根节点约束了其左右子树的取值范围,即其根节点的值是左子树值的上限,是其右子树值的下限。
因为提供了后序遍历序列,我们从后往前遍历,访问顺序就相当于从根节点到叶子,我们便可利用祖先节点的
上下限约束来判断孩子节点是否合法:
我们使用一个栈来保存各层祖辈节点,初始时,栈中入栈一个整数最小值,同时当前上限置为max_int
1.如果当前元素大于栈顶元素,则其可能为栈顶元素的右孩子
如果其大于max,则突破了当前子树的取值上限,不合法,返回false;
否则为当前栈顶的右孩子,入栈。
2.如果当前元素小于栈顶元素,则其为某个祖辈(栈中元素)的左孩子
不断的更新max为当前栈顶元素并出栈,直到当前元素不再小于栈顶为止。(此时当前元素为最后一个出栈元素的左孩子,当前上限自然为最后一个出栈的元素(该节点和其右孩子的上限都为其父节点))
当前元素入栈
所有元素遍历完毕,返回true。
class Solution {
public:
bool VerifySquenceOfBST(vector<int> &seq) {
if (seq.size() < 1) return false;
// roots栈里面依次存放各层祖辈节点的值
// 事先放入一个值以避免对空栈进行判断
stack<int> roots;
roots.push(INT_MIN);
int max = INT_MAX;
for (int i=seq.size()-1; i > -1; i--) {
// 当节点超过max约束时,它必定不是二叉搜索树
if (seq[i] > max) return false;
// 如果节点小于roots的栈顶,说明该节点是某个祖辈的左孩子
// 不断出栈,直到找出该祖辈,同时,该祖辈也提供了新的max约束
while (seq[i] < roots.top()) {
max = roots.top();
roots.pop();
}
// 该节点成了新一代的祖辈节点,为后续节点判断自己的位置提供依据
roots.push(seq[i]);
}
return true;
}
};