验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
思路:
方法1 对于每一个结点,步骤一 :也就是每一次都遍历左子树寻找左子树最大的节点,是否小于根节点。步骤二:遍历右子树找到右子树最小的节点,看是否大于根节点
class Solution { private TreeNode getMax(TreeNode node){ while(node.right!=null){//不会为null node = node.right; } return node; } private TreeNode getMin(TreeNode node){ while(node.left!=null){//不会为null node = node.left; } return node; } public boolean isValidBST(TreeNode root) { if(root == null) return true;//中序遍历所有节点,每一个节点强制小于后一个节点 if(root.left!=null&&getMax(root.left).val>=root.val){ return false;// 左边的最大值大于根节点,错误 } if(root.right!=null && getMin(root.right).val<=root.val){ return false;//右边的最小值小于root,错误 } return isValidBST(root.left)&&isValidBST(root.right);//如果根节点没问题,分别测试左右子树 } }
优点:好理解。缺点:每次都遍历一遍左子树和右子树,重复太多。
方法2: 步骤一:在遍历左子树的时候不断的更新左子树的值域 (root.left,max,root.val),步骤二 在遍历右子树的时候不断的更新右子树的值域(root.right,root.val,min).
class Solution { private boolean isOrder(TreeNode root,long min, long max){ if(root==null) return true; if(root.val<=min || root.val>=max){ return false; } return isOrder(root.left,min,root.val)&&isOrder(root.right,root.val,max); } public boolean isValidBST(TreeNode root) { return isOrder(root,Long.MIN_VALUE,Long.MAX_VALUE);//如果根节点没问题,分别测试左右子树 } }
非常高效的方法,不太好理解,就把一棵树看成只有三个节点能相对简单些。方法3:步骤一,考虑到是平衡二叉树,用中序遍历,可以得到一个有序数列。步骤二,每次比较当前节点和它的前一个节点。前一个节点用pre来表示,初始值Long.MAX_VALUE。如果小于等于前一个节点,那么返回false。
class Solution { private long pre = Long.MIN_VALUE;//当前节点的前一个值,如果当前节点比它前面的值还小,返回false public boolean isValidBST(TreeNode root) { if(root == null) return true; if(!isValidBST(root.left)){ return false; } if(root.val<=pre){ return false; } pre = root.val; return isValidBST(root.right); } }