golang avl树算法
package main
import (
"fmt"
"strings"
)
func abs(val int) int {
if val < 0 { return -val }
return val
}
var nodeCnt int
type Node struct {
val int
left, right *Node
h int
}
func max(i, j int) int {
if i > j {
return i
}
return j
}
func min(i, j int) int {
if i < j {
return i
}
return j
}
func (node *Node) height() int {
if node == nil {
return 0
}
return node.h
}
// 对节点y进行向右旋转操作,返回旋转后新的根节点x
// y x
// / \ / \
// x T4 向右旋转 (y) z y
// / \ - - - - - - - -> / \ / \
// z T3 T1 T2 T3 T4
// / \
// T1 T2
func adjustLeft(y *Node) *Node {
if y == nil {
panic("invalid node")
}
var x = y.left
y.left = x.right
x.right = y
y.h = max(y.left.height(), y.right.height()) + 1
x.h = max(x.left.height(), x.right.height()) + 1
return x
}
/*
y => x
a x y
b c xxxxxx
e d
*/
// right 重,左旋转
func adjustRight(y *Node) *Node {
if y == nil {
panic("invalid node")
}
var x = y.right
// x >= y
y.right = x.left
x.left = y
y.h = max(y.left.height(), y.right.height()) + 1
x.h = max(x.left.height(), x.right.height()) + 1
return x
}
// left 重, left.right 重
func adjustLeftRight(node *Node) *Node {
//左子树的右节点
node.left = adjustRight(node.left)
// left left rotation
return adjustLeft(node)
}
// right 重,并且 right.left 重
func adjustRightLeft(node *Node) *Node {
node.right = adjustLeft(node.right)
return adjustRight(node)
}
func insertNode(node *Node, val int) *Node {
if node == nil {
nodeCnt++
return &Node{val: val, h: 1}
}
switch {
case node.val < val:
// current < val , to right find
node.right = insertNode(node.right, val)
// 插入 右边节点,只能是 height(right) >= height(left)
if node.right.height()-node.left.height() == 2 {
// adjust right
if val > node.right.val {
// right 重,right.right也重
node = adjustRight(node)
} else {
// right 重,right.left重
node = adjustRightLeft(node)
}
}
case node.val > val:
// 去插入到左边节点
node.left = insertNode(node.left, val)
if node.left.height()-node.right.height() == 2 {
// 判断 left.val < val
if node.left.val > val {
// left重,left.left也重, 处理 ll
node = adjustLeft(node)
} else {
//left, left.right重
node = adjustLeftRight(node)
}
}
default:
//log.Println("exists")
}
node.h = max(node.left.height(), node.right.height()) + 1
return node
}
func findMinNode(node *Node) *Node {
if node == nil {
return nil
}
for node.left != nil {
node = node.left
}
return node
}
func findMaxNode(node *Node) *Node {
if node == nil {
return nil
}
for node.right != nil {
node = node.right
}
return node
}
// >= val => 天花板,下边界
func findFloorNode(node *Node, val int) *Node {
Loop:
for node != nil {
if node.val == val {
//return node
break Loop
} else if node.val < val {
// to right
node = node.right
} else {
//to left, if left is nil , return current Node
//node = node.right
left := findFloorNode(node.left, val)
if left != nil && left.val < node.val {
node = left
}
break Loop
// left is small
}
}
return node
}
// <= val 的最大节点
func findCeilNode(node *Node, val int) *Node {
// 早到 比 val 小的
if node == nil {
return nil
}
find:
for node != nil {
if node.val == val {
break find
} else if node.val > val {
// 比他大 , 左边 的 可能也比他大
node = node.left
} else {
// node.val < val , to right find <= val first
var s = findCeilNode(node.right, val)
if s != nil && s.val > node.val {
node = s
}
break find
}
}
return node
}
func adjustNode(node *Node) *Node {
// adjust node
switch node.left.height() - node.right.height() {
case 2:
// left 重
//var left = node.left
if node.left.height() > node.right.height() {
node = adjustLeft(node)
} else {
node = adjustLeftRight(node)
}
case -2:
if node.right.right.height() > node.right.left.height() {
// right right 重
node = adjustRight(node)
} else {
node = adjustRightLeft(node)
}
}
return node
}
func deleteNode(node *Node, val int) *Node {
if node == nil {
return nil
}
if node.val < val {
node.right = deleteNode(node.right, val)
} else if node.val > val {
// to left delete
node.left = deleteNode(node.left, val)
} else {
// delete current
nodeCnt--
if node.left == nil {
if node.right == nil {
//delete one
node = nil
} else {
// return node.right
node = node.right
}
} else {
if node.right == nil {
//node.left != nil
node = node.left
} else {
// node.left != nil node.right !=nil
//前驱节点
var nextNode = findMinNode(node.right)
node.val = nextNode.val
//委托 删除 minNode , 这边不好删除,直接 取巧 ,覆盖值即可
node.right = deleteNode(node.right, nextNode.val)
}
}
}
if node != nil {
//跳转高度
node.h = max(node.left.height(), node.right.height()) + 1
node = adjustNode(node)
}
return node
}
//func rightRotationNode(node *Node) *Node {
// var right = node.right
// node.right = node.left
// node
//}
func ascPrint(node *Node) {
if node == nil {
return
}
ascPrint(node.left)
fmt.Printf("%v,", node.val)
ascPrint(node.right)
}
func (o *Node)String() string {
return fmt.Sprintf("%v ",o.val)
}
func (o *Node) draw(prefix string, isTail bool, str *strings.Builder) {
if o.right != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
o.right.draw(newPrefix, false, str)
}
str.WriteString(prefix)
if isTail {
str.WriteString("└── ")
} else {
str.WriteString( "┌── ")
}
str.WriteString(o.String() + "\n")
if o.left != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
o.left.draw(newPrefix, true, str)
}
}
func main() {
var root *Node
root = insertNode(root,1)
root = insertNode(root,1)
root = insertNode(root,1)
root = insertNode(root,1)
for i:=88;i>=1;i-- {
root = insertNode(root,i)
}
var s strings.Builder
root.draw(" @ ", false, &s)
fmt.Println(s.String())
}
例题
220. 存在重复元素 III
Difficulty: **给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。 如果存在则返回 true,不存在返回 false。 示例 1: 输入:nums = [1,2,3,1], k = 3, t = 0 输出:true 示例 2: 输入:nums = [1,0,1,1], k = 1, t = 2 输出:true 示例 3: 输入:nums = [1,5,9,1,5,9], k = 2, t = 3 输出:false 提示: 0 <= nums.length <= 2 * 104 -231 <= nums[i] <= 231 - 1 0 <= k <= 104 0 <= t <= 231 - 1 **
给你一个整数数组 nums
和两个整数 k
和 t
。请你判断是否存在 两个不同下标 i
和 j
,使得 abs(nums[i] - nums[j]) <= t
,同时又满足 abs(i - j) <= k
。
如果存在则返回 true
,不存在返回 false
。
示例 1:
输入:nums = [1,2,3,1], k = 3, t = 0
输出:true
示例 2:
输入:nums = [1,0,1,1], k = 1, t = 2
输出:true
示例 3:
输入:nums = [1,5,9,1,5,9], k = 2, t = 3
输出:false
提示:
0 <= nums.length <= 2 * 10<sup>4</sup>
-2<sup>31</sup> <= nums[i] <= 2<sup>31</sup> - 1
0 <= k <= 10<sup>4</sup>
0 <= t <= 2<sup>31</sup> - 1
Solution
Language: ****
func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool {
var root *Node
//类似滑动窗口的算法
for i,n := 0,len(nums);i<n;i++ {
// 找到
// abs(nums[i] - nums[x]) <= t => 找上界 找小的 =》 nums[i] -t <= x <= nums[i] + t
var node = findFloorNode(root,nums[i] - t)
if node != nil && node.val <= nums[i] + t {
//满足 nums[i] -t <= node.val <= nums[i] + t => 即满足 表达式
return true
}
root = insertNode(root,nums[i])
// then can not find
if i>=k {
//删除划出窗口的元素
root = deleteNode(root,nums[i-k])
}
}
return false
}
func abs(val int) int {
if val < 0 { return -val }
return val
}
var nodeCnt int
type Node struct {
val int
left, right *Node
h int
}
func max(i, j int) int {
if i > j {
return i
}
return j
}
func min(i, j int) int {
if i < j {
return i
}
return j
}
func (node *Node) height() int {
if node == nil {
return 0
}
return node.h
}
// 对节点y进行向右旋转操作,返回旋转后新的根节点x
// y x
// / \ / \
// x T4 向右旋转 (y) z y
// / \ - - - - - - - -> / \ / \
// z T3 T1 T2 T3 T4
// / \
// T1 T2
func adjustLeft(y *Node) *Node {
if y == nil {
panic("invalid node")
}
var x = y.left
y.left = x.right
x.right = y
y.h = max(y.left.height(), y.right.height()) + 1
x.h = max(x.left.height(), x.right.height()) + 1
return x
}
/*
y => x
a x y
b c xxxxxx
e d
*/
// right 重,左旋转
func adjustRight(y *Node) *Node {
if y == nil {
panic("invalid node")
}
var x = y.right
// x >= y
y.right = x.left
x.left = y
y.h = max(y.left.height(), y.right.height()) + 1
x.h = max(x.left.height(), x.right.height()) + 1
return x
}
// left 重, left.right 重
func adjustLeftRight(node *Node) *Node {
//左子树的右节点
node.left = adjustRight(node.left)
// left left rotation
return adjustLeft(node)
}
// right 重,并且 right.left 重
func adjustRightLeft(node *Node) *Node {
node.right = adjustLeft(node.right)
return adjustRight(node)
}
func insertNode(node *Node, val int) *Node {
if node == nil {
nodeCnt++
return &Node{val: val, h: 1}
}
switch {
case node.val < val:
// current < val , to right find
node.right = insertNode(node.right, val)
// 插入 右边节点,只能是 height(right) >= height(left)
if node.right.height()-node.left.height() == 2 {
// adjust right
if val > node.right.val {
// right 重,right.right也重
node = adjustRight(node)
} else {
// right 重,right.left重
node = adjustRightLeft(node)
}
}
case node.val > val:
// 去插入到左边节点
node.left = insertNode(node.left, val)
if node.left.height()-node.right.height() == 2 {
// 判断 left.val < val
if node.left.val > val {
// left重,left.left也重, 处理 ll
node = adjustLeft(node)
} else {
//left, left.right重
node = adjustLeftRight(node)
}
}
default:
//log.Println("exists")
}
node.h = max(node.left.height(), node.right.height()) + 1
return node
}
func findMinNode(node *Node) *Node {
if node == nil {
return nil
}
for node.left != nil {
node = node.left
}
return node
}
func findMaxNode(node *Node) *Node {
if node == nil {
return nil
}
for node.right != nil {
node = node.right
}
return node
}
// >= val => 天花板,下边界
func findFloorNode(node *Node, val int) *Node {
Loop:
for node != nil {
if node.val == val {
//return node
break Loop
} else if node.val < val {
// to right
node = node.right
} else {
//to left, if left is nil , return current Node
//node = node.right
left := findFloorNode(node.left, val)
if left != nil && left.val < node.val {
node = left
}
break Loop
// left is small
}
}
return node
}
// <= val 的最大节点
func findCeilNode(node *Node, val int) *Node {
// 早到 比 val 小的
if node == nil {
return nil
}
find:
for node != nil {
if node.val == val {
break find
} else if node.val > val {
// 比他大 , 左边 的 可能也比他大
node = node.left
} else {
// node.val < val , to right find <= val first
var s = findCeilNode(node.right, val)
if s != nil && s.val > node.val {
node = s
}
break find
}
}
return node
}
func adjustNode(node *Node) *Node {
// adjust node
switch node.left.height() - node.right.height() {
case 2:
// left 重
//var left = node.left
if node.left.height() > node.right.height() {
node = adjustLeft(node)
} else {
node = adjustLeftRight(node)
}
case -2:
if node.right.right.height() > node.right.left.height() {
// right right 重
node = adjustRight(node)
} else {
node = adjustRightLeft(node)
}
}
return node
}
func deleteNode(node *Node, val int) *Node {
if node == nil {
return nil
}
if node.val < val {
node.right = deleteNode(node.right, val)
} else if node.val > val {
// to left delete
node.left = deleteNode(node.left, val)
} else {
// delete current
nodeCnt--
if node.left == nil {
if node.right == nil {
//delete one
node = nil
} else {
// return node.right
node = node.right
}
} else {
if node.right == nil {
//node.left != nil
node = node.left
} else {
// node.left != nil node.right !=nil
//前驱节点
var nextNode = findMinNode(node.right)
node.val = nextNode.val
//委托 删除 minNode , 这边不好删除,直接 取巧 ,覆盖值即可
node.right = deleteNode(node.right, nextNode.val)
}
}
}
if node != nil {
//跳转高度
node.h = max(node.left.height(), node.right.height()) + 1
node = adjustNode(node)
}
return node
}
//func rightRotationNode(node *Node) *Node {
// var right = node.right
// node.right = node.left
// node
//}
func ascPrint(node *Node) {
if node == nil {
return
}
ascPrint(node.left)
fmt.Printf("%v,", node.val)
ascPrint(node.right)
}