版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cds86333774/article/details/51203631
中序遍历法
首先,最直观的一种算法就是进行一次中序遍历,然后将每个节点的值保存在一个数组中,然后这个数组是有序的,那么这颗树就是一个二叉查找树。
小问题
但是这个算法有一个问题,那就是对于存在重复值的二叉查找树,它并不能判断其正确性,比如:
20.left = 20;
20.right = 20;
两者在数组中看起来是一样的。但是一个允许重复值存在的二叉查找树要约定好,插入一个重复的值,它应该在左边还是右边。
那么,现在我们假设不考虑有重复值的情况,这个算法就没有问题吗? 还可以优化吗?
我们不难发现,这个算法中的数组只是被用来判断序列是否有序。我们完全可以在遍历的时候就进行判断,从而节约存储空间。
代码
static int lastPrinted = Integer.MIN_VALUE;
public static boolean isBianrySearchTree(TreeNode root) {
if(root == null){
return true;
}
// 如果左子树不是二叉搜索树,则可以直接返回false
if(!isBianrySearchTree(root.left)){
return false;
}
// 再来判断此时跟节点的情况:是否比左子树的最大值大?
if(root.val < lastPrinted){
return false;
}
// 每访问一个节点,则更新一下 lastPrinted
lastPrinted = root.val;
if(!isBianrySearchTree(root.right)){
return false;
}
// 最后全部检查完了,还没有发现问题,则返回true
return true;
}
改进后的代码的优越性非常明显。如果有1万个节点,如果用数组的话则需要长度达到10000。但是用上面的方法,只用一个int 值。
区间检查法
先将区间设为[Integer.MIN_VALUE,Integer.MAX_VALUE],然后从根节利用前序遍历的方式检查每一个节点是否在特定区间内。进入左子树的时候更新max,进入右子树的时候,更新min。
public static boolean isBinarySearchTree2(TreeNode root) {
return isBinarySearchTree2(root, Integer.MIN_VALUE,Integer.MAX_VALUE );
}
private static boolean isBinarySearchTree2(TreeNode root, int min, int max) {
if(root == null){
return true;
}
// 检查根节点是否在区间内
if(root.val > max || root.val < min){
return false;
}else{
// 检查左子树,左子树的最大值就是根节点的值。
if(!isBinarySearchTree2(root.left, min, root.val)){
return false;
}
// 检查右子树,右子树的最小值就是根节点的值
if(!isBinarySearchTree2(root.right, root.val, max)){
return false;
}
}
return true;
}
测试
public static void main(String[] args) {
/***
* 新建一个二叉树:
*
* 15
* / \
* 12 25
* / \
* 9 13
* ***/
TreeNode root = new TreeNode(15);
TreeNode l = new TreeNode(12);
root.left = l;
TreeNode r = new TreeNode(25);
root.right = r;
TreeNode ll = new TreeNode(9);
TreeNode lr = new TreeNode(13);
l.left = ll;
l.right = lr;
System.out.println("方法一的判断 : "+ isBinarySearchTree(root));
System.out.println("方法二的判断 : "+ isBinarySearchTree2(root));
r.left = new TreeNode(40);
System.out.println("\n方法一的判断 : "+ isBinarySearchTree(root));
System.out.println("方法二的判断 : "+ isBinarySearchTree2(root));
}
输出
方法一的判断 : true
方法二的判断 : true
方法一的判断 : false
方法二的判断 : false