验证二叉搜索树
- https://leetcode.cn/problems/validate-binary-search-tree/
描述
- 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树
- 有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1
2
/ \
1 3
输入:root = [2,1,3]
输出:true
示例 2
5
/ \
1 4
/ \
3 6
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。
提示
- 树中节点数目范围在[1, 10410^4104] 内
- -2312^{31}231 <= Node.val <= 2312^{31}231 - 1
Typescript 版算法实现
1 )方案 1:中序遍历
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function isValidBST(root: TreeNode | null): boolean {
// 1. 声明最终存储树的数组
const traversalArr: number[] = [];
// 2. 定义基于中序遍历获取最终数组算法
function inorderTraverse(root: TreeNode | null): void {
if (!root) return;
inorderTraverse(root.left);
traversalArr.push(root.val);
inorderTraverse(root.right);
}
// 3. 开始中序遍历
inorderTraverse(root);
// 4. 验证当前数组是否符合要求
for (let i = 0, length = traversalArr.length; i < length - 1; i++) {
if (traversalArr[i] >= traversalArr[i + 1]) return false;
}
return true;
};
- 此方案是官方提供算法,用到了中序遍历的特性,它先遍历左子树,再遍历根节点,最后遍历右子树
- 而我们二叉搜索树保证了左子树的节点的值均小于根节点的值,根节点的值均小于右子树的值
- 因此中序遍历以后得到的序列一定是升序序列
- 最终进行验证的for循环就是检验是否是升序序列, 最终得到是否符合要求
- 这里有一个优化点是:最终保留了整个中序遍历的数组,实际上是不需要的
- 每一步最后添加的元素就足以知道是或不是二叉搜索树了,请看方案2
2 )方案 2:迭代法(中序遍历)
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function isValidBST(root: TreeNode | null): boolean {
let stack = []; // 存储的是未拜访过的树中的节点的值
let inorder = -Infinity; // 存储上一个中序遍历到的树节点值
while (stack.length || root) {
// 不断将当前树节点的左子节点加入栈, 直到没有左节点
while (root) {
stack.push(root);
root = root.left;
}
root = stack.pop(); // 将当前子树最左边的节点从栈中取出
// 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
if (root.val <= inorder) {
return false;
}
inorder = root.val; // 将当前节点的值设为 inorder
root = root.right; // 将当前右子节点作为根节点,继续遍历
}
return true;
};
- 此方案也是官方示例,是 中序遍历,用到了递归, 是深度优先遍历
- 核心思想是对比的每一步都进行是否满足要求的校验, 节省了方案1的存储空间
Python3 版算法实现
1 ) 方案 1:中序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
traversal_arr: List[int] = []
def inorder_traverse(node: Optional[TreeNode]) -> None:
if not node:
return
inorder_traverse(node.left)
traversal_arr.append(node.val)
inorder_traverse(node.right)
inorder_traverse(root)
for i in range(len(traversal_arr) - 1):
if traversal_arr[i] >= traversal_arr[i + 1]:
return False
return True
2 )方案 2:迭代法(中序遍历)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: Optional[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
Golang 版算法实现
1 ) 方案 1:中序遍历
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isValidBST(root *TreeNode) bool {
traversalArr := []int{}
var inorderTraverse func(node *TreeNode)
inorderTraverse = func(node *TreeNode) {
if node == nil {
return
}
inorderTraverse(node.Left)
traversalArr = append(traversalArr, node.Val)
inorderTraverse(node.Right)
}
inorderTraverse(root)
for i := 0; i < len(traversalArr)-1; i++ {
if traversalArr[i] >= traversalArr[i+1] {
return false
}
}
return true
}
2 ) 方案 2:迭代法(中序遍历)
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isValidBST(root *TreeNode) bool {
stack := []*TreeNode{}
inorder := -1 << 31 - 1 // 使用最小整数表示负无穷大
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
}
995



被折叠的 条评论
为什么被折叠?



