lc-go/solutions/1/q146/solution.go
2026-01-07 18:04:39 +09:00

112 lines
1.7 KiB
Go

package q146
type lruNode struct {
key, val int
prev, next *lruNode
}
type LRUCache struct {
cap int
index map[int]*lruNode
head, tail *lruNode
nodes []lruNode
p int
}
func Constructor(capacity int) LRUCache {
return LRUCache{
cap: capacity,
index: make(map[int]*lruNode, capacity),
nodes: make([]lruNode, capacity),
}
}
func (c *LRUCache) alloc() *lruNode {
if c.p < len(c.nodes) {
c.p++
return &c.nodes[c.p-1]
}
return nil
}
func (c *LRUCache) touch(node *lruNode) {
if node.prev == nil {
return
}
if c.tail == node {
c.tail = node.prev
} else {
node.next.prev = node.prev
}
node.prev.next = node.next
node.prev = nil
node.next = c.head
c.head.prev = node
c.head = node
}
func (c *LRUCache) evict() *lruNode {
if len(c.index) < c.cap {
return nil
}
node := c.tail
delete(c.index, node.key)
if node.prev == nil {
c.head, c.tail = nil, nil
} else {
c.tail = node.prev
c.tail.next = nil
}
return node
}
func (c *LRUCache) Get(key int) int {
node := c.index[key]
if node == nil {
return -1
}
c.touch(node)
return node.val
}
func (c *LRUCache) Put(key int, value int) {
if c.cap == 0 {
return
}
node := c.index[key]
if node != nil {
node.val = value
c.touch(node)
return
}
node = c.alloc()
if node == nil {
node = c.evict()
*node = lruNode{} // clear
}
node.key, node.val = key, value
c.index[key] = node
node.next = c.head
if c.head != nil {
c.head.prev = node
}
c.head = node
if c.tail == nil {
c.tail = node
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/