q98 验证二叉搜索树
题解
使用前序遍历,使用dfs来遍历,其中二叉排序树应该满足左子树的所有节点都小于根节点,右子树的所有节点都大于根节点。所以递归函数的参数列表中维护着一个最大值和最小值,在左递归的时候,将最大值更新为当前节点,因为左子树中不应该出现比这个最大值更大的数;同时在右递归的时候,将最小值更新为当前节点,因为右子树中不应该出现比这个最小值更小的数。
func isValidBST(root *TreeNode) bool {
return dfs(root, math.MinInt64, math.MaxInt64)
}
func dfs(root *TreeNode, min, max int) bool {
if root == nil {
return true
}
// 判断是否在这个区间内
if root.Val <= min || root.Val >= max {
return false
}
// 更新左递归的最大值为当前节点
// 更新右递归的最小值为当前节点
return dfs(root.Left, min, root.Val) && dfs(root.Right, root.Val, max)
}
q450 删除二叉搜索树中的节点
题解
删除BST中的节点,有以下三种情况:
1 如果key < root.Val,说明要删除的节点在BST的左子树,那么递归去左子树删除即可
2 如果key > root.Val,说明要删除的节点在BST的右子树,那么递归去右子树删除即可
3 如果key = root.Val,说明要删除的节点就是本节点,这一类又分以下三种情况:
- 无左右子树,直接删除即可
- 有右子树,将当前节点与后继节点替换,然后递归的在右子树中删除该后继节点
- 有左子树,将当前节点与前趋节点替换,然后递归的在左子树中删除该前趋节点
找前趋节点的方法,就是在当前节点的左子树中不断递归遍历它的右节点,直到右结点为空,当前节点就是前趋节点。
找后继节点的方法就是在当前节点的右子树中不断递归遍历它的左节点,直到左节点为空,当前节点就是后继节点。
func deleteNode(root *TreeNode, key int) *TreeNode {
if root == nil {
return nil
// 往左子树找
} else if key < root.Val {
root.Left = deleteNode(root.Left, key)
// 往右子树找
} else if key > root.Val {
root.Right = deleteNode(root.Right, key)
// 当前节点的值是key
} else {
// 无左右子树,直接删除
if root.Left == nil && root.Right == nil {
root = nil
// 有右子树,将后继节点换到当前位置,然后删除后继节点
} else if root.Right != nil {
// 替换
root.Val = Successor(root).Val
// 删除后继节点
root.Right = deleteNode(root.Right, root.Val)
// 有左子树,将前趋节点换到当前位置,然后删除前趋节点
} else {
root.Val = Predecessor(root).Val
root.Left = deleteNode(root.Left, root.Val)
}
}
return root
}
// Predecessor 寻找前趋节点
func Predecessor(node *TreeNode) *TreeNode {
pre := node.Left
for pre.Right != nil {
pre = pre.Right
}
return pre
}
// Successor 寻找后继节点
func Successor(node *TreeNode) *TreeNode {
post := node.Right
for post.Left != nil {
post = post.Left
}
return post
}
q538 把二叉搜索树转换为累加树
题解
这道题其实是要把根节点累加上右子树的和,然后左子树累加上根节点+右子树的和.
即:
root.Val = root.Val + root.Right.Val
root.Left.Val = root.Val
使用反向中序遍历即可.
func convertBST(root *TreeNode) *TreeNode {
sum := 0
var traversal func(root *TreeNode)
traversal = func(root *TreeNode) {
if root != nil {
traversal(root.Right)
sum += root.Val
root.Val = sum
traversal(root.Left)
}
}
traversal(root)
return root
}
q701 二叉搜索树中的插入操作
题解
插入时与当前节点进行比较,如果小于当前节点就继续遍历插入到左子树中,如果大于当前节点就继续遍历插入到右子树中。
func insertIntoBST(root *TreeNode, val int) *TreeNode {
if root == nil {
return &TreeNode{Val: val}
}
p := root
for p != nil {
if val < p.Val {
if p.Left == nil {
p.Left = &TreeNode{Val: val}
break
}
p = p.Left
} else {
if p.Right == nil {
p.Right = &TreeNode{Val: val}
break
}
p = p.Right
}
}
return root
}