BST 的合法性
由于 BST 需要满足以下条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
按照我们前面的理解是不是就会写出来
func isValidBST(root *TreeNode) bool {if root == nil {return true}if root.Left != nil && root.Val < root.Left.Val {return false}if root.Right != nil && root.Val > root.Right.Val {return false}return isValidBST(root.Left) && isValidBST(root.Right)}
需要注意这个算法里,只考虑到了父子节点的大小问题,没有考虑到祖孙节点的比较。
BST 需要的是 root 的所有左子树节点的值都小于 root.Val , 所有右子树节点的值都要大于 root.Val 。
所以可以引入
func isValidBST(root *TreeNode, min *TreeNode, max *TreeNode) bool {if root == nil {return true}if min != nil && root.Val < min.Val {return false}if max != nil && root.Val > max.Val {return false}return isValidBST(root.Left, nil, root) && isValidBST(root.Right, root, nil)}
这里的 min 和 max 不需要理解,只需要记住他们的作用是用来限制最大值和最小值的。
然后记住左子树的节点值都比 root.Val 小,右子树的节点都比 root.Val 大即可。
BST 中搜索一个数
func isInBST(root *TreeNode, target int) bool {if root == nil {return false}if root.Val == target {return true}return isInBST(root.Left, target) || isInBST(root.Right,target)}
这么写相当于穷举了所有的节点,适用于普通的二叉树。那么对于 BST 我们应该利用 左小右大 的特性。
func isInBST(root *TreeNode, target int) bool {if root == nil {return false}if root.Val == target {return true}if root.Val < target {return isInBST(root.Right, target)}if root.Val > target {return isInBST(root.Left, target)}}
BST 中插入一个数
这里需要理解为什么要生成新的节点
func insertIntoBST(root *TreeNode, val int) *TreeNode{if root == nil {return &TreeNode{Val: val}}if root.Val < val {root.Right = insertIntoBST(root.Right, val)}if root.Val > val {root.Left = insertIntoBST(root.Left, val)}return root}
BST 中删除一个数
删除一个节点时可能会触发这三种情况:
- 删除的节点正好是末端节点,没有子节点
- 删除节点存在一个子节点
- 删除节点存在两个子节点
其中第三个比较麻烦,为了不破坏 BST 的特性,A 必须找到左子树中最大的那个节点 或右子树中最小的节点来接替自己。
/*** Definition for a binary tree node.* type TreeNode struct {* Val int* Left *TreeNode* Right *TreeNode* }*/func deleteNode(root *TreeNode, key int) *TreeNode {if root == nil {return root}if root.Val == key {if root.Left == nil {return root.Right}if root.Right == nil {return root.Left}minNode := func(node *TreeNode) *TreeNode {for node.Left != nil {node = node.Left}return node}(root.Right)minNode.Left = root.Leftroot = root.Right} else if root.Val > key {root.Left = deleteNode(root.Left, key)} else {root.Right = deleteNode(root.Right, key)}return root}
