首页 > 试题广场 >

判断是不是二叉搜索树

[编程题]判断是不是二叉搜索树
  • 热度指数:103421 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个二叉树根节点,请你判断这棵树是不是二叉搜索树。

二叉搜索树满足每个节点的左子树上的所有节点均小于当前节点且右子树上的所有节点均大于当前节点。

例:
图1

图2

数据范围:节点数量满足 ,节点上的值满足
示例1

输入

{1,2,3}

输出

false

说明

如题面图1 
示例2

输入

{2,1,3}

输出

true

说明

如题面图2 

说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
var Min = (int)(^uint(0) >> 1)/-1
func isValidBST(root *TreeNode) bool {
	// write code here
	if root == nil {
		return true
	}

	if !isValidBST(root.Left) {
		return false
	}
    if root.Val <= Min{
        return false
    }else{
        Min = root.Val
    }
	if !isValidBST(root.Right){
        return false
    }
   
    return true
}

发表于 2024-05-19 21:34:06 回复(0)
func isValidBST( root *TreeNode ) bool {
    if root.Left != nil {
        // 检查左树是不是BST
        if !isValidBST(root.Left) {
            return false
        }

        // 判断左树最大值是否满足BST定义
        if maxNumInTree(root.Left) >= root.Val {
            return false
        }
    }

    if root.Right != nil {
        // 检查右树是不是BST
        if !isValidBST(root.Right) {
            return false
        }

        // 判断右树最大值是否满足BST定义
        if maxNumInTree(root.Right) <= root.Val {
            return false
        }
    }

    return true
}

// 当能保证输入的树是BST,且root不为空时可以使用
func maxNumInTree(root *TreeNode) int {
    for root.Right != nil {
        root = root.Right
    }

    return root.Val
}

编辑于 2024-04-09 15:41:23 回复(1)
有人知道最后一个用例为啥返回false么,最后一个用例只有左子树,左子树的最大值都小于根节点应该是TRUE啊,我辅助打印的数值为
max:2145690916
true
true
2146753918
9223372036854775807
左子树的最大值 2146753918 < 2147317028  最终结果应该是TRUE啊 
package main

import . "nc_tools"
import "math"
import "fmt"

/*
 * type TreeNode struct {
 *   Val int
 *   Left *TreeNode
 *   Right *TreeNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param root TreeNode类
 * @return bool布尔型
 */
func isValidBST(root *TreeNode) bool {
	if root == nil {
		return true
	}
	if root.Val == 2147317028 {
	levelOrder(root.Left)
	}

	isValidLeft, _, leftMax := validBSTNode(root.Left)
	isValidRight, rightMin, _ := validBSTNode(root.Right)
	fmt.Println(isValidLeft)
	fmt.Println(isValidRight)
	fmt.Println(leftMax)
	fmt.Println(rightMin)
	if leftMax != math.MinInt64 && int64(root.Val) <= leftMax {
		return false
	}
	if rightMin != math.MaxInt64 && int64(root.Val) >= rightMin {
		return false
	}
	return isValidLeft && isValidRight
}

func validBSTNode(root *TreeNode) (bool, int64, int64) {
	if root == nil {
		return true, math.MaxInt64, math.MinInt64
	}
	min, max := int64(root.Val), int64(root.Val)
	isValidLeft, leftMin, leftMax := validBSTNode(root.Left)
	isValidRight, rightMin, rightMax := validBSTNode(root.Right)

	if leftMax > max {
		max = leftMax
	}
	if rightMax > max {
		max = rightMax
	}
	if leftMin < min {
		min = leftMin
	}
	if rightMin < min {
		min = rightMin
	}
	return isValidLeft && isValidRight, min, max
}

func v2(root *TreeNode) bool {
	// arr 用来装当前层的所有node
	arr := []*TreeNode{root}
	res := make([][]*TreeNode, 0)
	for len(arr) > 0 {
		// 记录当前层次要遍历的总长度
		currentLevelLen := len(arr)
		// 记录当前层次遍历的结果
		curLevel := make([]*TreeNode, 0, len(arr))
		for i := 0; i < currentLevelLen; i++ {
			curLevel = append(curLevel, arr[i])
			if arr[i] == nil {
				continue
			}
			arr = append(arr, arr[i].Left)
			arr = append(arr, arr[i].Right)
		}
		// arr 是复用变量,使用结束后只留下下一层的元素
		arr = arr[currentLevelLen:]
		res = append(res, curLevel)
	}

	for index, lArr := range res {
		fmt.Printf("第%v行:", index+1)
		for _, lNum := range lArr {
			if lNum == nil {
				fmt.Print("# ")
			} else {
				fmt.Print(fmt.Sprint(lNum.Val) + " ")
			}
		}
		fmt.Println()
	}

	return false
}

func levelOrder(root *TreeNode) [][]int {
	if root == nil {
		return nil
	}
	// arr 用来装当前层的所有node
	arr := []*TreeNode{root}
	res := make([][]int, 0)
	for len(arr) > 0 {
		// 记录当前层次要遍历的总长度
		currentLevelLen := len(arr)
		// 记录当前层次遍历的结果
		curLevel := make([]int, 0, len(arr))
		for i := 0; i < currentLevelLen; i++ {
			if arr[i] == nil {
				continue
			}
			curLevel = append(curLevel, arr[i].Val)
			if arr[i].Left != nil {
				arr = append(arr, arr[i].Left)
			}
			if arr[i].Right != nil {
				arr = append(arr, arr[i].Right)
			}
		}
		// arr 是复用变量,使用结束后只留下下一层的元素
		arr = arr[currentLevelLen:]
		res = append(res, curLevel)
	}
	max := res[1][0]
	for index, lArr := range res {
		if index == 0 {
			continue
		}
		for _, lNum := range lArr {
			if lNum > max {
				max = lNum
			}
		}
	}
	fmt.Printf("max:%v\n", max)
	return res
}


发表于 2023-07-06 01:07:33 回复(0)
var pre *TreeNode = nil

func isValidBST( root *TreeNode ) bool {
    if root == nil {
        return true
    }
    if !isValidBST(root.Left) {
        return false
    }
    if pre == nil {
        pre = root
    } else {
        if root.Val < pre.Val {
            return false
        }
    }
    pre = root
    return isValidBST(root.Right)
}

发表于 2023-05-13 16:56:53 回复(1)
递归,判断根节点是否大于左子树的最大值,是否下于右子树的最小值
func isValidBST(root *TreeNode) bool {
	if root == nil {
		return true
	}
    ok, _, _ := isBST(root)
	return ok
}

func isBST(root *TreeNode) (bool, int, int) {
    if root == nil {
        return true, -1 << 31, 1 << 31 -1
    }
	if root != nil && root.Left == nil && root.Right == nil  {
		return true, root.Val, root.Val
	}
    isl, maxl, minl := isBST(root.Left)
    isr, maxr, minr := isBST(root.Right)
    if maxr == 1 << 31 -1 {
        maxr = root.Val
    }
    if minl == -1 << 31 {
        minl = root.Val
    }
    if isl && isr && root.Val >= maxl && root.Val <= minr {
        return true, maxr, minl
    } else {
        return false, maxr, minl
    }
}


发表于 2022-12-19 16:08:02 回复(0)
题解:看到二叉树先写一个中序遍历,
根据前面将二叉树变成双向链表的方法的改良,即前一个节点与当前节点进行比较,若大于就是不符合的,用一个变量将结果存起来,最后返回这个变量即可。
func isValidBST(root *TreeNode) bool {
	var dfs func(root *TreeNode)
	var result bool = true
	var pre *TreeNode
	dfs = func(root *TreeNode) {
		if root == nil {
			return
		}
		dfs(root.Left)
		if pre == nil {
			pre = root
		} else {
			if pre.Val > root.Val {
				result = false
				pre = root
				return
			}
			pre = root
		}
		dfs(root.Right)
	}
	dfs(root)
	return result
	// write code here
}


发表于 2022-11-15 11:29:52 回复(1)
package main
// import "fmt"
import . "nc_tools"
/*
 * type TreeNode struct {
 *   Val int
 *   Left *TreeNode
 *   Right *TreeNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param root TreeNode类 
 * @return bool布尔型
*/
func isValidBST( root *TreeNode ) bool {
    // write code here
    if root==nil{
        return true
    }
    left:=root.Left
    right:=root.Right
    if left!=nil{
        if root.Val<left.Val{
            return false
        }
    }
    if right!=nil{
        if root.Val>right.Val{
            return false
        }
    }
    return isValid(left,root.Val,true)&&isValid(right,root.Val,false)
}

func isValid(root *TreeNode,n int,flag bool) bool{
    if root==nil{
        return true
    }
    left:=root.Left
    right:=root.Right
    if left!=nil{
        if root.Val<left.Val{
            return false
        }
        if flag{
           if left.Val>n{
                return false
            }
        }else{
            if left.Val<n{
                return false
            }
        }
    }
    if right!=nil{
        if root.Val>right.Val{
            return false
        }
        if flag{
            if right.Val>n{
                return false
            }
        }else{
            if right.Val<n{
                return false
            }
        }
    }
    return isValid(left,root.Val,true)&&isValid(right,root.Val,false)
}
发表于 2022-04-01 18:27:00 回复(1)