LeetCode 75 —— 98. 验证二叉搜索树
一、题目描述:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:root = [2,1,3]
输出:true
示例 2:输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。提示:
树中节点数目范围在[1, 10^4] 内
-2^31 <= Node.val <= 2^31 - 1来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/validate-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
这道题目我的思路无非是两种,一种用递归,另一种用栈这种数据结构。
用递归写起来比较简单,因为是二叉搜索树,要求左子树所有节点都小于根节点,右子树所有节点都大于根节点。所以我们需要进行根节点与其左右节点的比较。
所以我们可以用一个函数,其初始传入根节点和int64的最小值和最大值作为lower和upper。然后在函数中,我们通过判断当前节点是否大于lower并且小于upper,如果不符合,即return false。然后我们再递归进入root.Left和root.Right。如果是root.Left的话,其lower不变,其upper变成其根节点root的Val。如果是root.Right的话,其upper不变,其lower变成根节点root的Val。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是,刚开始没有将问题合理建模:
return helper(root.Left,lower,root.Val) && helper(root.Right,root.Val,upper)
这里没有写对,通过重新分析,是先将左边的与lower和根节点的值进行比较,然后再将右边子树的节点与根节点的值和upper进行比较。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
二叉搜索树 **中序遍历 **得到的值构成的序列一定是升序的,这启示我们在中序遍历的时候实时检查当前节点的值是否大于前一个中序遍历到的节点的值即可。
func isValidBST(root *TreeNode) bool { stack := []*TreeNode{} inorder := math.MinInt64 for len(stack) > 0 || root != nil { for root != nil { stack = append(stack, root) root = root.Left } root = stack[len(stack)-1] stack = stack[:len(stack)-1] if root.Val <= inorder { return false } inorder = root.Val root = root.Right } return true } 作者:LeetCode-Solution 链接:https://leetcode.cn/problems/validate-binary-search-tree/solution/yan-zheng-er-cha-sou-suo-shu-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、AC 代码:
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func isValidBST(root *TreeNode) bool { return helper(root,math.MinInt64,math.MaxInt64) } func helper(root *TreeNode,lower, upper int) bool { if root == nil { return true } if root.Val >= upper || root.Val <= lower{ return false } return helper(root.Left,lower,root.Val) && helper(root.Right,root.Val,upper) }
四、总结:
递归的时间复杂度和空间复杂度都是O(n),使用栈,也就是中序遍历的空间复杂度和时间复杂度都是O(n)。