2025-03-20-02

This commit is contained in:
2025-03-20 18:27:05 +08:00
parent 181f2da899
commit 7d854201b4
3 changed files with 257 additions and 1 deletions

View File

@@ -3,6 +3,133 @@
2^x = 1 << x
x/2 x >> 1
~~~
## 快乐数
~~~ go
func isHappy(n int) bool {
slow, fast := n, step(n)
for fast != 1 && slow != fast {
slow = step(slow)
fast = step(step(fast))
}
return fast == 1
}
func step(n int) int {
sum := 0
for n > 0 { //通过循环逐位计算
sum += (n%10) * (n%10)
n = n/10
}
return sum
}
~~~
## 查找二维数组
~~~ go
func searchMatrix(matrix [][]int, target int) bool {
row := sort.Search(len(matrix), func(i int) bool { return matrix[i][0] > target }) - 1
if row < 0 {
return false
}
col := sort.SearchInts(matrix[row], target)
return col < len(matrix[row]) && matrix[row][col] == target
}
~~~
## LRU缓存
~~~ go
// 定义LRU缓存结构体包含当前大小最大容量键值对映射表以及双向链表的头尾节点
type LRUCache struct {
size int // 当前缓存中元素的数量
capacity int // 缓存的最大容量
cache map[int]*DLinkedNode // 键到节点的映射表用于快速查找节点
head, tail *DLinkedNode // 双向链表的虚拟头节点和虚拟尾节点便于操作边界条件
}
// 定义双向链表节点结构体包含键值以及前后指针
type DLinkedNode struct {
key, value int // 节点存储的数据键和值
prev, next *DLinkedNode // 指向前一个和后一个节点的指针
}
// 初始化一个双向链表节点仅设置键和值前后指针默认为nil
func initDLinkedNode(key, value int) *DLinkedNode {
return &DLinkedNode{
key: key,
value: value,
}
}
// 构造函数创建一个新的LRU缓存实例并初始化其内部数据结构
func Constructor(capacity int) LRUCache {
l := LRUCache{
cache: make(map[int]*DLinkedNode), // 初始化键值对映射表
head: initDLinkedNode(0, 0), // 创建虚拟头节点
tail: initDLinkedNode(0, 0), // 创建虚拟尾节点
capacity: capacity, // 设置缓存最大容量
}
l.head.next = l.tail // 将虚拟头节点指向虚拟尾节点
l.tail.prev = l.head // 将虚拟尾节点指向虚拟头节点
return l // 返回构造好的LRU缓存实例
}
// 根据给定键从LRU缓存中获取对应的值如果不存在则返回-1
func (this *LRUCache) Get(key int) int {
if _, ok := this.cache[key]; !ok { // 判断键是否存在于缓存中
return -1 // 如果不存在直接返回-1
}
node := this.cache[key] // 获取到对应节点
this.moveToHead(node) // 将该节点移动到链表头部表示最近访问
return node.value // 返回节点的值
}
// 向LRU缓存中添加或更新键值对如果缓存已满则移除最久未使用的节点
func (this *LRUCache) Put(key int, value int) {
if _, ok := this.cache[key]; !ok { // 判断键是否已经存在于缓存中
node := initDLinkedNode(key, value) // 创建新节点
this.cache[key] = node // 将新节点加入到映射表中
this.addToHead(node) // 将新节点添加到链表头部表示最近访问
this.size++ // 增加缓存大小计数
if this.size > this.capacity { // 如果缓存大小超过最大容量
removed := this.removeTail() // 移除链表尾部节点(最久未使用)
delete(this.cache, removed.key) // 删除映射表中对应的键值对
this.size-- // 减少缓存大小计数
}
} else { // 如果键已经存在
node := this.cache[key] // 获取到对应节点
node.value = value // 更新节点的值
this.moveToHead(node) // 将该节点移动到链表头部(表示最近访问)
}
}
// 将指定节点添加到双向链表头部
func (this *LRUCache) addToHead(node *DLinkedNode) {
node.prev = this.head // 设置节点的前驱为虚拟头节点
node.next = this.head.next // 设置节点的后继为原头部节点
this.head.next.prev = node // 将原头部节点的前驱指向当前节点
this.head.next = node // 将虚拟头节点的后继指向当前节点
}
// 从双向链表中移除指定节点
func (this *LRUCache) removeNode(node *DLinkedNode) {
node.prev.next = node.next // 将前驱节点的后继指向后继节点
node.next.prev = node.prev // 将后继节点的前驱指向前驱节点
}
// 将指定节点移动到双向链表头部
func (this *LRUCache) moveToHead(node *DLinkedNode) {
this.removeNode(node) // 首先移除该节点
this.addToHead(node) // 然后将其添加到链表头部
}
// 移除双向链表尾部节点并返回该节点
func (this *LRUCache) removeTail() *DLinkedNode {
node := this.tail.prev // 获取尾部节点(不包括虚拟尾节点)
this.removeNode(node) // 移除该节点
return node // 返回被移除的节点
}
~~~
## 加油站
在一条环路上有 `n` 个加油站,其中第 `i` 个加油站有汽油 `gas[i]` 升。