链接:https://leetcode-cn.com/problems/validate-binary-search-tree/
给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:
示例 1:
输入:
2
/ \
1 3
输出: true
示例 2:
输入:
5
/ \
1 4
/ \
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。根节点的值为 5 ,但是其右子节点值为 4 。
https://leetcode-cn.com/problems/validate-binary-search-tree/solution/die-dai-yu-di-gui-by-powcai/
根据题意,我们知道了二叉搜索树的定义,当前节点的值要大于其左子树,当前节点的值要小于其右子树,同时其左子树和右子树也要是一颗二叉搜索树。要想知道一棵二叉树是不是二叉搜索树,肯定需要对树遍历一次,一般对于二叉树的遍历有广度优先搜索和深度优先搜索两种方法,广度优先搜索运用了迭代的技巧,而深度优先搜索则运用了递归的技巧。同时,二叉树的深度优先遍历还可以根据访问根节点位置的不同,而分为前序遍历、中序遍历和后序遍历。根据二叉搜索树的定义,我们可以知道,如果这颗二叉搜索树按照中序遍历进行排列,那它是一个上升的序列。接下来,我们就一一来分析下。
这里我们着重理解一下上界和下界:
时间复杂度:O(n)
空间复杂度:O(n)
Python:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
def helper(root,lower=float('-inf'),upper=float('inf')):
if not root:
return True
val=root.val
if val<=lower or val>=upper:
return False
if not helper(root.right,val,upper):
return False
if not helper(root.left,lower,val):
return False
return True
return helper(root)
简写一下:
class Solution:
def isValidBST(self, root: TreeNode, low = float('-inf'), high = float('inf')) -> bool:
if not root:return True
if not low<root.val<high:return False
return self.isValidBST(root.left,low,root.val) and self.isValidBST(root.right,root.val,high)
Go:
/**
* 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 <= lower || root.Val >= upper{
return false
}
return helper(root.Left, lower, root.Val) && helper(root.Right, root.Val, upper)
}
思路和递归一样,只是使用了迭代的方式。
时间复杂度 : O(n),每个结点访问一次。
空间复杂度 : O(n)
Python:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
stack=[(root,float('-inf'),float('inf')),]
while stack:
root,lower,upper=stack.pop()
if not root:
continue
val=root.val
if val>=upper or val<=lower:
return False
stack.append((root.right,val,upper))
stack.append((root.left,lower,val))
return True
讲中序遍历时,我们先看下上面迭代代码的这两行:
stack.append((root.right,val,upper))
stack.append((root.left,lower,val))
其实这两行对于这里,没有任何顺序而言,先插入左子节点,或者先插入右子节点,都是可以的。大家知道,前序遍历是 根左右 的顺序,中序遍历是 左根右 的顺序,后序遍历是 左右根 的顺序。上述代码,如果先插入右子节点,后插入左子节点,是前序遍历;如果先插入左子节点,后插入右子节点,则不是三种遍历的任意一种。
注意:栈弹出节点用的是 pop()。
开头我们了解了,如果一棵树是二叉搜索树,那么它的中序遍历的序列是一个上升的序列,所以我们可以通过一个 inorder 序列,来检查序列中的每个元素是否小于其下一个元素。
时间复杂度 : 最坏情况下为 O(n),这种情况是树为二叉搜索树或破坏条件的元素是最右叶子节点。
空间复杂度 : O(n)
Python:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
stack=[]
inorder=float('-inf')
while stack or root:
while root:
stack.append(root)
root=root.left
root=stack.pop()
if root.val <= inorder:
return False
inorder=root.val
root=root.right
return True
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
stack=[]
inorder=float('-inf')
while stack or root:
if root:
stack.append(root)
root=root.left
else:
root=stack.pop()
if root.val <= inorder:
return False
inorder=root.val
root=root.right
return True
Go:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isValidBST(root *TreeNode) bool {
var stack []*TreeNode
inorder := math.MinInt64
for root != nil || len(stack) > 0{
for root != nil{
stack=append(stack,root)
root=root.Left
}
index := len(stack)-1
root = stack[index]
stack = stack[:index]
if root.Val <= inorder{
return false
}
inorder = root.Val
root = root.Right
}
return true
}
如果觉得文章不错,希望大家可以扫描上方名片关注我的微信公众号噢,点赞、收藏、在看、分享就再好不过了。如果有任何建议和问题,可以在下方给我留言,我会及时回复的,同时会不定期更新更多的文章,祝我们终将自由。