leetcode+二叉树+验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 1:

输入:
    2
   / \
  1   3
输出: true
示例 2:

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
     根节点的值为 5 ,但是其右子节点值为 4 。

github链接

解答该题要注意不仅右子节点要大于该节点,整个右子树的元素都应该大于该节点

方法一:递归

思路:在遍历树的同时保留节点的上界与下界,比较时要同时考虑子节点和上下界的值

  • 将节点的值与上界和下界进行比较
  • 根据节点的值对左子树右子树的上界下届分别进行更新
  • 左子树和右子树递归完成该过程

时间复杂度:O(N)  每个节点访问一次,判断该节点是否小于上界及右子节点,大于下界及左子节点。

空间复杂度:O(N)  跟进整个树

	public boolean help_isValidBST(TreeNode node,Integer lower,Integer upper) {
		if (node==null) return true;
		
		int val=node.val;
		System.out.println(lower+" "+val+" "+upper);
		
		if(val<=lower) return false;
		if(val>=upper) return false;
		if (!help_isValidBST(node.right,val,upper)) return false;
		if (!help_isValidBST(node.left,lower,val)) return false;
		return true;
	}
	public boolean isValidBST0(TreeNode node) {
		return help_isValidBST(node,Integer.MIN_VALUE,Integer.MAX_VALUE);
	}

方法二:迭代

思路:利用队列先进先出的特点,迭代进行广度优先遍历

  • 将t层的元素从右向左依次入队
  • 将t层元素逐个出队,根据其上下界值判定是否满足二叉搜索树(必要条件)
  • 将其子节点入队,同时对入队元素的上下界值进行更新

时间复杂度:O(N)  每个节点访问一次

空间复杂度:O(N)  跟进整个树

	public void update(TreeNode node,Integer lower,Integer upper,
			Queue<TreeNode> queue,Queue<Integer> lowers,Queue<Integer> uppers) {
		queue.add(node);
		lowers.add(lower);
		uppers.add(upper);
		if (node!=null)
			System.out.println(lower+" "+node.val+" "+upper+" "+queue.size());
	}
	public boolean isValidBST1(TreeNode node) {
		Queue<TreeNode> queue=new LinkedList<TreeNode>();
		Queue<Integer> uppers=new LinkedList<Integer>(),
		lowers=new LinkedList<Integer>();
		Integer lower=Integer.MIN_VALUE, upper=Integer.MAX_VALUE,val;
		update(node,lower,upper,queue,lowers,uppers);
		
		while(!queue.isEmpty()) {
			node=queue.poll();
			lower=lowers.poll();
			upper=uppers.poll();
			if(node==null) continue;
			val=node.val;
			
			if(val<=lower) return false;
			if(val>=upper) return false;
			update(node.right,val,upper,queue,lowers,uppers);
			update(node.left,lower,val,queue,lowers,uppers);
		}
		return true;
	}
	

方法三:

思路:利用栈后进先出的特点,通过中序遍历实现深度优先遍历

  • 找到当前节点t最左的分支t_left,进行判定,对其进行中序遍历left-inorder-right及判定
  • 节点t_left出栈,判定t节点,并对t进行中序遍历及判定

注意:

  1. 中序遍历对于二叉搜索树即可得到由小到大的数
  2. t_left为最左分支,即二叉搜索树的最小值
  3. 判定过程仅需大于前一个值即可
	public boolean isValidBST2(TreeNode node) {
		Stack<TreeNode> stack=new Stack();
		double inorder=-Double.MAX_VALUE;
		while(!stack.isEmpty() || node!=null) {
			while(node!=null) {
				stack.push(node);
				node=node.left;
			}			
			node=stack.pop();
			if (node!=null)
				System.out.println(inorder+" "+node.val+" "+stack.size());
			if(node.val<=inorder) return false;
			inorder=node.val;
			node=node.right;
			if (node!=null)
				System.out.println(node.val);
		}
		return true;
	}

给一个大牛的代码:

思路:利用中序遍历,仅需一次递归调用

  1. 基于二叉树的中序遍历-->从小到大遍历
  2. 定义一个变量存储上一遍历节点的值-->x下界
  3. 递归遍历二叉树
  4. 左子树返回true,对比根结点与缓存变量
  5. 若4成立,根结点的值赋给缓存变量
  6. 递归遍历右子树
	double last=-Double.MAX_VALUE;
	public boolean isValidBST(TreeNode root) {
		if(root==null)
			return true;
		if(isValidBST(root.left)) {
			System.out.println(last+" "+root.val);
			if(last<root.val) {
				last=root.val;
				return isValidBST(root.right);
			}
		}
		return false;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值