146. LRU 緩存機制
運用你所掌握的數據結構,設計和實現一個 LRU (最近最少使用) 緩存機制 。
實現 LRUCache 類:
LRUCache(int capacity) 以正整數作為容量 capacity 初始化 LRU 緩存
int get(int key) 如果關鍵字 key 存在于緩存中,則返回關鍵字的值,否則返回 -1 。
void put(int key, int value) 如果關鍵字已經存在,則變更其數據值;如果關鍵字不存在,則插入該組「關鍵字-值」。當緩存容量達到上限時,它應該在寫入新數據之前刪除最久未使用的數據值,從而為新的數據值留出空間。
進階:你是否可以在 O(1) 時間復雜度內完成這兩種操作?
示例:
輸入
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
輸出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解釋
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 緩存是 {1=1}
lRUCache.put(2, 2); // 緩存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 該操作會使得關鍵字 2 作廢,緩存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 該操作會使得關鍵字 1 作廢,緩存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
解題思路
基于鏈表和hashmap實現LRU
- 每次新增key的時候,如果key已經存在了,就將key移到鏈表頭,并且修改value。如果key不存在,直接將key插入隊頭。如果已經超出LRU的大小,就刪除鏈表尾部的key
- 每次get的時候,如果key存在,就將這個key移到鏈表頭,并且返回
代碼
type LRUCache struct {capacity inthead *Nodetail *Nodecache map[int]*Node
}
type Node struct {pre *Nodenext *Nodekey intval int
}var c LRUCache
func Constructor(capacity int) LRUCache {c.cache= map[int]*Node{}c.capacity=capacityc.head=&Node{val: -1}c.tail=&Node{val: -1}c.head.next=c.tailc.tail.pre=c.headreturn c
}func (lru *LRUCache) Get(key int) int {node,ok := c.cache[key]if ok {p,n := node.pre,node.nextp.next=nn.pre=pth:=lru.head.next//插入頭節點lru.head.next=nodenode.pre=lru.headnode.next=thth.pre=nodereturn node.val}return -1
}func (lru *LRUCache) Put(key int, value int) {if lru.Get(key)!=-1 {lru.head.next.val=valuereturn}if lru.capacity==0 {delete(lru.cache,lru.tail.pre.key)tl := lru.tail.pre.pretl.next=lru.taillru.tail.pre=tllru.capacity++}node := &Node{key: key,val: value,next: lru.head.next,pre: lru.head,}lru.head.next.pre=nodelru.head.next=nodelru.cache[key]=nodelru.capacity--
}/*** Your LRUCache object will be instantiated and called as such:* obj := Constructor(capacity);* param_1 := obj.Get(key);* obj.Put(key,value);*/