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)
传递允许子树的范围,根节点的范围在,实现上可以传入int能表示的最小值,最大值math.MinInt64,math.MaxInt64;或者用nil表示
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
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
*/