98. 验证二叉搜索树

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

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

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

输入:

  2
 /  \
1   3

输出: true
示例 2:

输入:

   5
  / \
 1   4
 /   \
3     6

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

  • 分析
    该题目,就是要遍历整个树,然后对于每个节点i,是否都大于其左子树上的节点,是否都小于其右子树上的节点;bst是全局的
    Top-down:see code1 时间O(n)
    传递允许子树的范围,根节点的范围在(,+)(-\infty,+\infty),实现上可以传入int能表示的最小值,最大值math.MinInt64,math.MaxInt64;或者用nil表示\infty
    Down-top:see code2 时间O(n)
    本文采用返回分支上的区间,供节点比较,实现判断,判断过程如下图,比较的顺序是自底向上,实现上没有top-down简介高效。
    此外,还有,通过LNR遍历整个树到栈上,检查栈顺序元素是否严格有序,时间空间都是O(n);最笨办法,对于每个节点,遍历其子树获得最大最小,时间O(n^2)。

  • code1

package main

import (
	"fmt"
)

type TreeNode struct {
  Val int
  Left *TreeNode
  Right *TreeNode
}
func BST(root*TreeNode,l,r *int)bool {
	if root == nil {
		return true
	}
	if l!=nil&&*l>=root.Val||r!=nil&&root.Val>=*r{
		return false
	}
	return BST(root.Left,l,&root.Val)&&
			BST(root.Right,&root.Val,r)

}

func isValidBST(root *TreeNode) bool {
	return BST(root,nil,nil)
}
func main(){

	var t1,t2,t3,t4,t5,t6 TreeNode
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t1.Val=5;t2.Val=14;t3.Val=1
	t1.Left=&t2;t2.Left=&t3
	fmt.Println(isValidBST(&t1))
	t1.Val=2;t1.Left=&t2;t1.Right=&t3
	t2.Val=1;t3.Val=3
	fmt.Println(isValidBST(&t1))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t4.Val=4;t5.Val=5;t6.Val=6
	t5.Left=&t1;t1.Left=nil;t1.Right=nil
	t5.Right=&t4;t4.Left=&t3;t4.Right=&t6
	fmt.Println(isValidBST(&t5))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t1.Val=10;t2.Val=5;t3.Val=15;t4.Val=6;t5.Val=20
	t1.Left=&t2;t1.Right=&t3;t3.Left=&t4;t3.Right=&t5
	fmt.Println(isValidBST(&t1))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t1.Val=1
	fmt.Println(isValidBST(&t1))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	fmt.Println(isValidBST(&t1))
}
/*
false
false
false
false
true
true
*/
  • code2
    98. 验证二叉搜索树
package main

import (
	"fmt"
)

type TreeNode struct {
  Val int
  Left *TreeNode
  Right *TreeNode
}
func BST(root*TreeNode)(int,int,bool){
	if root==nil{
		return 0,0,true
	}
	if root.Left==nil&&root.Right==nil{
		return root.Val,root.Val,true
	}
	var t bool
	var a1,a2,a3,a4 int
	if root.Left!=nil{
		a1,a2,t=BST(root.Left)
		if !t||a2>=root.Val{//子树为空,则返回其本身,【root.val,];若子树不空,则判断其区间大小是否符合要求
			return root.Val,root.Val,false
		}
	}else{
		a1=root.Val
	}
	if root.Right!=nil{
		a3,a4,t=BST(root.Right)//子树为空,则返回其本身,【,root.val]
		if !t||root.Val>=a3{
			return root.Val,root.Val,false
		}
	}else{
		a4=root.Val
	}
	//范围root子树元素区间的并,[a1,a4]
	return a1,a4,true
}
func isValidBST(root *TreeNode) bool {
	_,_,t:=BST(root)
	return t
}
func main(){
	var t1,t2,t3,t4,t5,t6 TreeNode
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t1.Val=5;t2.Val=14;t3.Val=1
	t1.Left=&t2;t2.Left=&t3
	fmt.Println(isValidBST(&t1))
	t1.Val=2;t1.Left=&t2;t1.Right=&t3
	t2.Val=1;t3.Val=3
	fmt.Println(isValidBST(&t1))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t4.Val=4;t5.Val=5;t6.Val=6
	t5.Left=&t1;t1.Left=nil;t1.Right=nil
	t5.Right=&t4;t4.Left=&t3;t4.Right=&t6
	fmt.Println(isValidBST(&t5))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t1.Val=10;t2.Val=5;t3.Val=15;t4.Val=6;t5.Val=20
	t1.Left=&t2;t1.Right=&t3;t3.Left=&t4;t3.Right=&t5
	fmt.Println(isValidBST(&t1))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	t1.Val=1
	fmt.Println(isValidBST(&t1))
	t1=TreeNode{};t2=t1;t3=t1;t4=t1;t5=t1;t6=t1
	fmt.Println(isValidBST(&t1))
}
/*
false
false
false
false
true
true
*/

相关文章: