福哥答案2020-09-18:node
方法:哈希表 + 雙向鏈表。
時間複雜度:對於 put 和 get 都是 O(1)。
空間複雜度:O(capacity),由於哈希表和雙向鏈表最多存儲 capacity+1 個元素。緩存
代碼用go語言編寫,代碼以下:spa
package test40_lru import ( "fmt" "testing" ) /* 哈希表 + 雙向鏈表 時間複雜度:對於 put 和 get 都是 O(1)O(1)。 空間複雜度:O(capacity),由於哈希表和雙向鏈表最多存儲 capacity+1 個元素。 */ //https://leetcode-cn.com/problems/lru-cache/solution/lruhuan-cun-ji-zhi-by-leetcode-solution/ //go test -v -test.run TestLru func TestLru(t *testing.T) { cache := NewLRUCache(2) cache.Put(1, 1) cache.Put(2, 2) cache.Get(1) // 返回 1 cache.Put(3, 3) // 該操做會使得關鍵字 2 做廢 cache.Get(2) // 返回 -1 (未找到) cache.Put(4, 4) // 該操做會使得關鍵字 1 做廢 cache.Get(1) // 返回 -1 (未找到) cache.Get(3) // 返回 3 cache.Get(4) // 返回 4 } type LRUCache struct { size int capacity int cache map[int]*DLinkedNode head, tail *DLinkedNode } type DLinkedNode struct { key, value int prev, next *DLinkedNode } func NewDLinkedNode(key, value int) *DLinkedNode { return &DLinkedNode{ key: key, value: value, } } func NewLRUCache(capacity int) LRUCache { l := LRUCache{ cache: map[int]*DLinkedNode{ }, head: NewDLinkedNode(0, 0), tail: NewDLinkedNode(0, 0), capacity: capacity, } l.head.next = l.tail l.tail.prev = l.head return l } //獲取元素 func (f *LRUCache) Get(key int) int { //若是緩存裏未找到元素 if _, ok := f.cache[key]; !ok { fmt.Println(-1) return -1 } //緩存裏有元素 node := f.cache[key] //若是 key 存在,先經過哈希表定位,再移到頭部 f.moveToHead(node) fmt.Println(node.value) return node.value } //放入元素 func (f *LRUCache) Put(key int, value int) { //若是緩存裏沒有元素 if _, ok := f.cache[key]; !ok { node := NewDLinkedNode(key, value) f.cache[key] = node //放在頭部 f.addToHead(node) f.size++ //若是元素個數大於容量,須要刪除元素 if f.size > f.capacity { //刪除鏈表尾部 removed := f.removeTail() //刪除map中的key delete(f.cache, removed.key) f.size-- } } else { //緩存裏有元素 //獲取元素 node := f.cache[key] //修改值 node.value = value //移動到鏈表頭 f.moveToHead(node) } } //添加到頭節點 func (f *LRUCache) addToHead(node *DLinkedNode) { node.prev = f.head node.next = f.head.next f.head.next.prev = node f.head.next = node } //刪除節點 func (f *LRUCache) removeNode(node *DLinkedNode) { node.prev.next = node.next node.next.prev = node.prev } //移動到頭節點 func (f *LRUCache) moveToHead(node *DLinkedNode) { f.removeNode(node) f.addToHead(node) } //刪除尾部 func (f *LRUCache) removeTail() *DLinkedNode { node := f.tail.prev f.removeNode(node) return node }
執行結果以下:
code
評論blog