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

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;
    }



    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/x_i_y_u_e/article/details/52288862
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞