LRUCache设计和实现
题目说明
数据结构设计
- 操作
- 关键点
实现1
package main
import (
"fmt"
)
type Node struct {
Key interface{}
Value interface{}
pre *Node
next *Node
}
type LRUCache struct {
limit int
HashMap map[interface{}]*Node // k: 缓存key v: 缓存v
head *Node
end *Node // 缓存中最后一个节点
}
func (l *LRUCache) removeNode(node *Node) interface{} {
if node == l.end { // 删除尾节点
l.end = l.end.pre
l.end.next = nil
} else if node == l.head { // 删除头节点
l.head = l.head.next
l.head.pre = nil
} else { // 删除中间节点
node.pre.next = node.next
node.next.pre = node.pre
}
return node.Key
}
func (l *LRUCache) addNode(node *Node) {
// 往空链表插入节点
if l.end != nil {
l.end.next = node
node.pre = l.end
node.next = nil
}
l.end = node
if l.head == nil {
l.head = node
}
}
func (l *LRUCache) refreshNode(node *Node) {
if node == l.end {
return
}
l.removeNode(node) // 从链表中的任意位置移除原来的位置
l.addNode(node) // 添加到链表的尾部
}
func Constructor(capacity int) LRUCache {
lruCache := LRUCache{limit: capacity}
lruCache.HashMap = make(map[interface{}]*Node, capacity)
return lruCache
}
func (l *LRUCache) Get(key interface{}) interface{} {
if v, ok := l.HashMap[key]; ok {
l.refreshNode(v)
return v.Value
} else {
return -1
}
}
func (l *LRUCache) Put(key, value interface{}) {
if v, ok := l.HashMap[key]; !ok {
if len(l.HashMap) >= l.limit {
oldkey := l.removeNode(l.head)
delete(l.HashMap, oldkey)
}
node := Node{Key: key, Value: value}
l.addNode(&node)
l.HashMap[key] = &node
} else {
v.Value = value
l.refreshNode(v)
}
}
func (l *LRUCache) getCache() {
for n := l.head; n != nil; n = n.next {
fmt.Println(n.Key, n.Value)
}
}
func main() {
cache := Constructor(3)
cache.Put(11, 1)
cache.Put(22, 2)
cache.Put(33, 3)
cache.Put(44, 4)
fmt.Println("before")
cache.getCache()
v := cache.Get(33)
fmt.Println("after get", v)
cache.getCache()
}
实现2
实现3
采用双向链表,标准库container/list提供了双向链表
利用map对链表节点进行索引
记录缓存大小
https://leetcode-cn.com/problems/lru-cache/solution/lru-go-jie-fa-by-shi-xiao-shi/