二叉搜索树系列 2
验证二叉搜索树
https://leetcode-cn.com/problems/validate-binary-search-tree/
注意:这题有坑,左右子树都是 BST 的一棵树,它自己不一定是 BST(还需要左右子树的值都小于或大于自己)。因此不能简单的递归交给子树解决,而要将根节点的限制也作为函数参数传入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| func isValidBST(root *TreeNode) bool { return isValid(root, nil, nil) }
func isValid(root, min, 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 isValid(root.Left, min, root) && isValid(root.Right, root, max) }
|
或者走一遍中序遍历,判断是否有元素比上一个元素小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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 }
|
二叉搜索树中的搜索
https://leetcode-cn.com/problems/search-in-a-binary-search-tree/
递归和迭代两种方法,最坏情况下时间复杂度都是 O(N) (因为不是平衡
BST,最坏情况下退化成一个链表)。
空间复杂度,最坏情况下递归还是栈空间的 O(N),而迭代是 O(1),没使用额外空间。
递归
1 2 3 4 5 6 7 8 9 10
| func searchBST(root *TreeNode, val int) *TreeNode { if root == nil || root.Val == val { return root } if val < root.Val { return searchBST(root.Left, val) } else { return searchBST(root.Right, val) } }
|
迭代
1 2 3 4 5 6 7 8 9 10
| func searchBST(root *TreeNode, val int) *TreeNode { for root != nil && root.Val != val { if val < root.Val { root = root.Left } else { root = root.Right } } return root }
|
二叉搜索树中的插入
https://leetcode-cn.com/problems/insert-into-a-binary-search-tree/
类似于搜索,只不过需要对返回值赋值。一旦涉及「改」,函数就要返回 TreeNode
类型,并且对递归调用的返回值进行接收。
1 2 3 4 5 6 7 8 9 10 11
| func insertIntoBST(root *TreeNode, val int) *TreeNode { if root == nil { return &TreeNode{val, nil, nil} } if val < root.Val { root.Left = insertIntoBST(root.Left, val) } else { root.Right = insertIntoBST(root.Right, val) } return root }
|
删除二叉搜索树中的节点
https://leetcode-cn.com/problems/delete-node-in-a-bst/
记住接受函数的返回值。删除一个节点,如果它左右子树都不为空,则最好的方法是找一个替代它,使得新的节点还能满足 BST。右子树中的最小节点和左子树中的最大节点都能满足这个要求,只要用它们替换掉待删除的节点即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| func deleteNode(root *TreeNode, key int) *TreeNode { if root == nil { return root } if key < root.Val { root.Left = deleteNode(root.Left, key) return root } else if key > root.Val { root.Right = deleteNode(root.Right, key) return root } else { if root.Right == nil { return root.Left } if root.Left == nil { return root.Right } minNode := findMin(root.Right)
root.Right = deleteNode(root.Right, minNode.Val)
minNode.Right = root.Right minNode.Left = root.Left root = minNode return root } }
func findMin(root *TreeNode) *TreeNode { for root.Left != nil { root = root.Left } return root }
|
注意这里我们不改变节点的值,只操作它的指针。