112 lines
1.7 KiB
Go
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);
|
|
*/
|