题目
- LRU 缓存机制
题目描述
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。 实现 LRUCache 类:
LRUCache(int capacity)以正整数作为容量capacity初始化LRU缓存
int get(int key)如果关键字key存在于缓存中,则返回关键字的值,否则返回 -1。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。 当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
思考
哈希表查找快,但是数据没有固定顺序;链表有顺序之分,插入、删除快,但是查找慢;所以结合一下,形成一种新得数据结构:哈希链表LinkedHashMap
代码
package leetcode
import (
"encoding/json"
"log"
)
// 单个节点
type Node struct {
key int
val int
prev *Node
next *Node
}
type DoubleList struct {
// 链表元素个数
size int
// 头尾节点
head *Node
tail *Node
}
// InitDoubleList
// 初始化双向链表
func InitDoubleList() *DoubleList {
list := &DoubleList{
head: &Node{},
tail: &Node{},
}
list.head.next = list.tail
list.tail.prev = list.head
list.size = 0
return list
}
// AddLast
// 在链表尾部添加节点x,时间复杂度O(1)
func (list *DoubleList) AddLast(x *Node) {
x.prev = list.tail.prev
x.next = list.tail
list.tail.prev.next = x
list.tail.prev = x
list.size++
}
// Remove
// 删除链表中x节点(x一定存在)
// 由于是双链表且给得目标Node节点,时间复杂度为O(1)
func (list *DoubleList) Remove(x *Node) {
// 前一个节点的下一个为x节点得下一个
x.prev.next = x.next
// 下一个节点的前一个为x节点的前一个
x.next.prev = x.prev
list.size--
}
// RemoveFirst
// 删除链表中第一个节点,并返回该节点,时间复杂度为O(1)
func (list *DoubleList) RemoveFirst() *Node {
// 校验是否双向链表为空
if list.head.next == list.tail {
return nil
}
first := list.head.next
list.Remove(first)
return first
}
// Size
// 返回链表长度,时间复杂度O(1)
func (list *DoubleList) Size() int {
return list.size
}
type LRUCache struct {
hashMap map[int]*Node
cache *DoubleList
cap int
}
// Constructor
// 初始化
func Constructor(capacity int) LRUCache {
return LRUCache{
hashMap: map[int]*Node{},
cache: InitDoubleList(),
cap: capacity,
}
}
// makeRecently
// 将key提升为最近使用得
func (this *LRUCache) makeRecently(key int) {
x, ok := this.hashMap[key]
// 校验是否存在
if !ok {
return
}
this.cache.Remove(x)
this.cache.AddLast(x)
}
// addRecently
// 添加最近使用得元素
func (this *LRUCache) addRecently(key, val int) {
x := &Node{key: key, val: val}
// 链表尾部就是最近使用得元素
this.cache.AddLast(x)
// 在map中添加key得映射
this.hashMap[key] = x
}
// deleteKey
// 删除某一个key
func (this *LRUCache) deleteKey(key int) {
x, ok := this.hashMap[key]
// 校验是否存在
if !ok {
return
}
this.cache.Remove(x)
delete(this.hashMap, key)
}
// removeLeastRecently
// 删除最久未使用的元素
func (this *LRUCache) removeLeastRecently() {
x := this.cache.RemoveFirst()
if x == nil {
return
}
key := x.key
delete(this.hashMap, key)
}
// Get
func (this *LRUCache) Get(key int) int {
node, ok := this.hashMap[key]
if !ok {
return -1
}
this.makeRecently(key)
return node.val
}
// Put
func (this *LRUCache) Put(key int, value int) {
if _, ok := this.hashMap[key]; ok {
// 删除旧的数据
this.deleteKey(key)
// 新插入的数据为最近使用的数据
this.addRecently(key, value)
return
}
if this.cap == this.cache.Size() {
// 删除最近未使用的元素
this.removeLeastRecently()
}
// 添加为最近使用的元素
this.addRecently(key, value)
}
func (this *LRUCache) Println() {
if rs, err := json.Marshal(this.hashMap); err == nil {
log.Println(string(rs))
}
}
参考
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/lr…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
[算法小抄@付东来]