检查一颗二叉树是否是二叉查找树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cds86333774/article/details/51203631

中序遍历法

首先,最直观的一种算法就是进行一次中序遍历,然后将每个节点的值保存在一个数组中,然后这个数组是有序的,那么这颗树就是一个二叉查找树。

小问题

但是这个算法有一个问题,那就是对于存在重复值的二叉查找树,它并不能判断其正确性,比如:

20.left = 2020.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

猜你喜欢

转载自blog.csdn.net/cds86333774/article/details/51203631
今日推荐