思路一:最大/最小值法:
通过自上而下传递每个结点的最大值和最小值的方法解决问题。顺序为先序遍历的顺序
从min = Integer.MIN_VALUE,max = Integer.MAX_VALUE开始,根节点的值val必然在这个范围内。
处理左子树:
新区间:max更新为父节点的的val(左子结点<父节点的val),min为父节点区间的最小值(这个不好理解,画图仔细想)
处理右子树:
新区建:min更新为父节点的的val(右子结点>父节点的val),max即为父节点区间的最大值
public static boolean checkBST(Node root) {
return checkBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
private static boolean checkBST(Node root, int minValue, int maxValue) {
if (root == null) {
return true;
}
//一旦不在区间内,就不是BTS
if (root.value < minValue || root.value > maxValue) {
return false;
}
//左结点不能>父节点,右结点不能<父节点
if (!checkBST(root.left, minValue, root.value) || !checkBST(root.right, root.value, maxValue)) {
return false;
}
return true;
}
思路二:遍历法
根据二叉搜素树的性质,可以知道,任意一棵二叉搜素树的中序遍历(左,根,右)是有序的,因此可以采取遍历的方式。
代码实现:
代码相对来说,比较简单,只需将二叉树的非递归中序遍历(参考以下链接)的输出部分,变为判断部分即可。
public class checkBST2 {
public static boolean isBST(Node root){
if(root == null){
return true;
}
int res = Integer.MIN_VALUE;//用于保存前一个结点的值
Stack<Node> stack = new Stack<>();
while(root != null || !stack.isEmpty()){
if(root != null){
stack.push(root);
root = root.left;
}else{
root = stack.pop();
// 判断部分:BST输出是递增的,如果当前值比前一个结点更小,说明不是BST
if(root.data < res){
return false;
}else{
res = root.data;
root = root.right;
}
}
}
return true;
}
思路三:
递归中序遍历的方式
// preval记录上个结点的值,注意是成员变量不是局部变量,保证在递归中变量值的实时变化
int preval=Integer.MIN_VALUE;
public boolean checkBST2(Node root) {
if (root == null)
return true;
boolean leftCheck = checkBST2(root.left);
if (root.value < preval) {
return false;
} else {
preval = root.value;
}
boolean rightCheck = checkBST2(root.right);
return leftCheck && rightCheck;
}