先来看题目:
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
我们都知道一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:
2
/
1 3
输出: true
示例 2:
输入:
5
/
1 4
/
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
解题思路:
本题用递归的思路来解决。递归的话我们关注3个点
1、如何判断递归结束
本题中,我们要判断的是二叉搜索树的左边节点小于跟节点,右边节点大于跟节点
if (preNode!=null&&preNode!!.val>=root.val){
return false
}
2、循环条件是什么,遍历左边和右边节点
3、返回啥值,是否是搜素遍历二叉树
按照中序遍历的特性,返回的是一个顺序列表,我们可以利用这一特性,来解决这个问题。 if (dataList[i] <= dataList[i - 1]) { return false } 解题步骤:
递归 1
class Solution {
var preNode:TreeNode? = null
fun isValidBST(root: TreeNode?): Boolean {
if (root==null) return true
val left = isValidBST(root.left)
if (preNode!=null&&preNode!!.val>=root.val){
return false
}
preNode = root
val right = isValidBST(root.right)
return left&&right
}
}
递归2 val dataList = mutableListOf() fun isValidBST(root: TreeNode?): Boolean { searchBst(root) for (i in 1 until dataList.size) { if (dataList[i] <= dataList[i - 1]) { return false } } return true }
fun searchBst(root: TreeNode?) {
if (root == null) return
searchBst(root.left)
dataList.add(root.val)
searchBst(root.right)
}
来看看用中序遍历的复杂度
时间复杂度 : O(n),其中 n 为二叉树的节点个数。二叉树的每个节点最多被访问一次,因此时间复杂度为 O(n)。
空间复杂度 : O(n),其中 n 为二叉树的节点个数。栈最多存储 n 个节点,因此需要额外的 O(n) 的空间。