判断一个二叉树是不是合法的二分查找树

来源:互联网 发布:巴丁算法集 编辑:程序博客网 时间:2024/05/01 05:36

leetcode题目https://leetcode.com/problems/validate-binary-search-tree/,判断一个二叉树是不是合法的二分查找树,这个题目应该说遇到多次了,然而在写的时候还是费了一番时间,而且写了一个十分拙劣的算法(在本文最后,不做解释)。

参考leetcode的discuss,遇到了两个比较好的解法,一个是递归(同样是递归,人家的就很简单),另一个非递归。

先看递归,递归的话采用自顶向下的方式比较简单,自顶向下,也就是自父节点向子节点传递范围要求(子节点不能大于某个值,不能小于某个值),比自底向上要方便的多,看代码,采用Long.MIN_VALUE是防止根节点是Integer.MIN_VALUE,那就通不过了:

    /* 判断一个二叉树是不是合法的二分查找树的简单的递给方法,学习     * 采用自顶向下的遍历方式,对于每个节点,检查顶部传来的范围要求,     * 要求是指:对于左子树,父节点的值就是最大值,对于右子树,父节点的值就是最小值     */    public boolean isValidBST(TreeNode root) {        //初始的时候,对根节点没有范围要求        return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);    }        public boolean isValidBST(TreeNode root, long minVal, long maxVal) {        if (root == null) return true;                //检查是否满足根节点的范围要求        if (root.val >= maxVal || root.val <= minVal)         return false;        //修改对子节点的要求,对于左子树,本节点的值就是最大值,对于右子树,本节点的值就是最小值        return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);    }

再看非递归,非递归的方式比递归的方式速度要慢,但是很明显非递归能有效的减小栈空间的使用量,防止栈溢出。思路是使用中序非递归遍历(这里有二叉树的非递归中序遍历),跟中序非递归遍历基本完全一致,就是保存了一个前驱节点,并在每次访问一个节点的时候更新前驱节点,如果前驱节点的值大于等于当前节点,那就是非二分查找树,因为二分查找树的中序遍历是一个递增序列。看代码:

/*判断一个二叉树是不是合法的二叉树的非递归遍历 * 采用中序遍历,并保存一个前驱节点,这样在每检查一个 * 节点的时候,就跟前驱节点对比,如果比前驱节点小(或者等于) * 就表示不合法 */    public boolean isValidBST(TreeNode root){          Stack<TreeNode> stack = new Stack<TreeNode>();                  //设置前驱节点        TreeNode pre = null;                while(root!=null || !stack.isEmpty()){              while(root!=null){      //将当前节点,以及左子树一直入栈,循环结束时,root==null                  stack.push(root);                  root = root.left;              }              root = stack.pop();                          //比较并更新前驱,与普通遍历的区别就在下面四行            if(pre!=null && root.val<= pre.val){            return false;            }            pre = root;                        root = root.right;  //访问右子树          }                 return true;      }  

我的拙劣的算法:

    public boolean isValidBST(TreeNode root) {            if(root==null){    return true;    }    int[] minMax = new int[2];        return minMax(root, minMax);    }            public boolean minMax(TreeNode root,int[] minMax){    if(root!=null&&root.left==null&&root.right==null){    minMax[0] = root.val;    minMax[1] = root.val;    return true;    }        int[] left = null;    int[] right = null;        if(root.left!=null){    left = new int[2];    boolean bin = minMax(root.left, left);    if(!bin){    return false;    }    }    if(root.right!=null){    right = new int[2];    boolean bin = minMax(root.right,right);    if(!bin){    return false;    }    }        if((left==null||left!=null&&root.val>left[1])    &&(right==null||right!=null&&root.val<right[0])){        if(left!=null&&right!=null){    minMax[0] = Math.min(Math.min(left[0], right[0]),root.val);        minMax[1] = Math.max(Math.max(left[1], right[1]),root.val);    }else if(left!=null){    minMax[0] = Math.min(left[0],root.val);    minMax[1] = Math.max(left[1],root.val);    }else{    minMax[0] = Math.min(right[0],root.val);    minMax[1] = Math.max(right[1],root.val);      }    return true;    }        return false;    }




0 0