1. 二叉搜索树的最近公共祖先
相比上一周的二叉树的最近公共祖先。
二叉搜索树的最近公共祖先可以利用二叉搜索树的特性,通过寻找第一个夹在两节点中间的节点。
1.1 递归法
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root.Val>p.Val && root.Val>q.Val{
return lowestCommonAncestor(root.Left,p,q)
}
if root.Val<p.Val && root.Val<q.Val{
return lowestCommonAncestor(root.Right,p,q)
}
return root
}
1.2 迭代法
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
for root!=nil{
if root.Val>p.Val && root.Val>q.Val{
root = root.Left
}else if root.Val<p.Val && root.Val<q.Val{
root = root.Right
}else{
return root
}
}
return nil
}
2. 二叉搜索树种的插入操作
2.1 递归法
func insertIntoBST(root *TreeNode, val int) *TreeNode {
if root==nil{
return &TreeNode{ Val : val }
}
if root.Val > val{
root.Left = insertIntoBST(root.Left,val)
}else if root.Val < val{
root.Right = insertIntoBST(root.Right,val)
}
return root
}
2.2 迭代法
通过迭代寻找要查找的位置,同时保留该位置的前一个指针。
func insertIntoBST(root *TreeNode, val int) *TreeNode {
pre,rootStore := root,root
for root != nil{
pre = root
if root.Val<val{
root = root.Right
}else{
root = root.Left
}
}
if pre == nil{
return &TreeNode{
Val: val,
}
}else{
if pre.Val>val{
pre.Left = &TreeNode{
Val: val,
}
}else{
pre.Right = &TreeNode{
Val: val,
}
}
}
return rootStore
}
3. 删除二叉搜索树中的节点
3.1 递归法
方法1:使用了双指针,将要删除节点的左节点挂载到删除节点的右节点的最左节点的左节点下
func deleteOneNode(target *TreeNode) *TreeNode {
if target == nil {
return target
}
if target.Right == nil {
return target.Left
}
//寻找目标节点右子树的最左节点
cur := target.Right
for cur.Left != nil {
cur = cur.Left
}
//将目标节点的左子树,嫁接到目标节点右子树的最左节点
cur.Left = target.Left
return target.Right
}
func deleteNode(root *TreeNode, key int) *TreeNode {
// 特殊情况处理
if root == nil {
return root
}
cur := root
var pre *TreeNode
for cur != nil {
if cur.Val == key {
break
}
pre = cur
if cur.Val > key {
cur = cur.Left
} else {
cur = cur.Right
}
}
if pre == nil {//没找到或者要删除的就是根节点
return deleteOneNode(cur)
}
// pre 要知道是删除左孩子还有右孩子
if pre.Left != nil && pre.Left.Val == key {
pre.Left = deleteOneNode(cur)
}
if pre.Right != nil && pre.Right.Val == key {
pre.Right = deleteOneNode(cur)
}
return root
}
3.2 迭代法
方式1:将要删除节点的左节点挂载到删除节点的右节点的最左节点的左节点下
func deleteNode(root *TreeNode, key int) *TreeNode {
//1.未找到该key,返回nil
if root==nil{
return nil
}
//找到了要删除的节点
if root.Val == key{
//2.删除的节点没有孩子节点
if root.Left==nil && root.Right==nil{
root=nil
return nil
}else if root.Left==nil{ //3.删除的还没有左节点,那么返回右节点
root = root.Right
return root
}else if root.Right==nil{ //4.删除的还没有右节点,那么返回左节点
root = root.Left
return root
}else{//5.删除的节点有左右孩子节点
//可以将要删除节点的左节点挂载到删除节点的右节点的最左节点的左节点下
mostLeft := root.Right
for mostLeft.Left!=nil{
mostLeft = mostLeft.Left
}
mostLeft.Left = root.Left
root = root.Right
return root
}
}
//要删除的节点可能在左边
if root.Val > key{
root.Left = deleteNode(root.Left,key)
}
//要删除的节点可能在右边
if root.Val < key{
root.Right = deleteNode(root.Right,key)
}
return root
}
方式2:将要删除节点的右节点的最左节点,与要删除的节点调换位置。
func deleteNode(root *TreeNode, key int) *TreeNode {
// 特殊情况处理
if root == nil {
return root
}
if key<root.Val{
root.Left = deleteNode(root.Left,key)
}else if root.Val<key{
root.Right = deleteNode(root.Right,key)
}else{
//能进到这里说明已经找到需要删除的节点了
if root.Right == nil{
return root.Left
}else if root.Left == nil{
return root.Right
}else{
//说明两个子节点均存在
minnode := root.Right
for minnode.Left != nil {
minnode = minnode.Left
}
root.Val = minnode.Val
root.Right = deleteNode1(root.Right)
return root
}
}
return root
}
func deleteNode1(root *TreeNode)*TreeNode {
if root.Left==nil{
tempR := root.Right
root.Right = nil
return tempR
}
//递归查找删除点
root.Left = deleteNode1(root.Left)
return root
}
4. 修剪二叉搜索树
4.1 递归法
func trimBST(root *TreeNode, low int, high int) *TreeNode {
if root==nil{
return root
}
if root.Val<low{
return trimBST(root.Right,low,high)
}
if root.Val>high{
return trimBST(root.Left,low,high)
}
root.Left = trimBST(root.Left,low,high)
root.Right = trimBST(root.Right,low,high)
return root
}
4.2 迭代法
func trimBST(root *TreeNode, low int, high int) *TreeNode {
if root==nil{
return root
}
// 处理root,让root移动到[low,high]范围内,注意是左闭右闭
for root != nil && (root.Val < low || root.Val > high){
if root.Val < low{
root = root.Right
} else {
root = root.Left
}
}
cur := root
// 此时root已经在[low,high]范围内,处理左孩子元素小于 low 的情况(左节点是一定小于 root.Val,因此天然小于 high)
for cur != nil{
for cur.Left != nil && cur.Left.Val < low{
cur.Left = cur.Left.Right
}
cur = cur.Left
}
cur = root
// 此时 root 已经在[low, high] 范围内,处理右孩子大于 high 的情况
for cur != nil{
for cur.Right != nil && cur.Right.Val >high{
cur.Right = cur.Right.Left
}
cur = cur.Right
}
return root
}
5. 将有序数组转换为二叉搜索树
5.1 本题
5.1.1 递归法
每次取数组中间的数作为节点,利用双指针。
func sortedArrayToBST(nums []int) *TreeNode {
l,r := 0,len(nums)-1
return createTreeNode(nums,l,r)
}
func createTreeNode(nums []int, l,r int)*TreeNode{
if l>r{
return nil
}
mid := (l+r)/2
root := &TreeNode{Val:nums[mid]}
root.Left = createTreeNode(nums,l,mid-1)
root.Right = createTreeNode(nums,mid+1,r)
return root
}
//更加优雅的写法
func sortedArrayToBST(nums []int) *TreeNode {
if len(nums) == 0 { //终止条件,最后数组为空则可以返回
return nil
}
idx := len(nums)/2
root := &TreeNode{Val: nums[idx]}
root.Left = sortedArrayToBST(nums[:idx])
root.Right = sortedArrayToBST(nums[idx+1:])
return root
}
6. 把二叉搜索树转换为累加树
var pre int
func convertBST(root *TreeNode) *TreeNode {
pre = 0
traversal(root)
return root
}
func traversal(cur *TreeNode){
if cur == nil {
return
}
traversal(cur.Right)
cur.Val += pre
pre = cur.Val
traversal(cur.Left)
}
7. 额外题目
7.1 从中序与后序遍历序列构造二叉树
func buildTree(inorder []int, postorder []int) *TreeNode {
idxMap := map[int]int{}
for i, v := range inorder {
idxMap[v] = i
}
return createNode(0, len(inorder)-1, &postorder, idxMap)
}
func createNode(inorderLeft, inorderRight int, postorder *[]int, idxMap map[int]int) *TreeNode {
// 无剩余节点
if inorderLeft > inorderRight {
return nil
}
// 后续遍历的末尾元素即为当前子树的根节点
length := len(*postorder)
val := (*postorder)[length-1]
*postorder = (*postorder)[:length-1]
root := &TreeNode{Val: val}
// 根据 val 在中序遍历的位置,将中序遍历划分成左右两颗子树
// 由于我们每次都从后序遍历的末尾取元素,所以要先遍历右子树再遍历左子树
inorderRootIndex := idxMap[val]
root.Right = createNode(inorderRootIndex+1, inorderRight, postorder, idxMap)
root.Left = createNode(inorderLeft, inorderRootIndex-1, postorder, idxMap)
return root
}
7.2 从中序与前序遍历序列构造二叉树
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func buildTree(preorder []int, inorder []int) *TreeNode {
idxMap := map[int]int{}
for i, v := range inorder {
idxMap[v] = i
}
return createTree(0, len(inorder)-1, &preorder, idxMap)
}
func createTree(inorderLeft,inorderRight int,preorder *[]int,idxMap map[int]int)*TreeNode{
if inorderLeft>inorderRight{
return nil
}
val := (*preorder)[0]
*preorder = (*preorder)[1:]
index := idxMap[val]
root := &TreeNode{Val:val}
root.Left = createTree(inorderLeft,index-1,preorder,idxMap)
root.Right = createTree(index+1,inorderRight,preorder,idxMap)
return root
}
7.3 最大二叉树
func constructMaximumBinaryTree(nums []int) *TreeNode {
if len(nums)==0{
return nil
}
maxIndex := findMaxIndex(nums)
root := &TreeNode{Val:nums[maxIndex]}
root.Left = constructMaximumBinaryTree(nums[:maxIndex])
root.Right = constructMaximumBinaryTree(nums[maxIndex+1:])
return root
}
func findMaxIndex(nums []int)int{
maxIndex := 0
for i:=1;i<len(nums);i++{
if nums[i]>nums[maxIndex]{
maxIndex = i
}
}
return maxIndex
}