# [146. LRU Cache](https://leetcode.com/problems/lru-cache/) ## 题目 Design a data structure that follows the constraints of a **[Least Recently Used (LRU) cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU)**. Implement the `LRUCache` class: - `LRUCache(int capacity)` Initialize the LRU cache with **positive** size `capacity`. - `int get(int key)` Return the value of the `key` if the key exists, otherwise return `1`. - `void put(int key, int value)` Update the value of the `key` if the `key` exists. Otherwise, add the `key-value` pair to the cache. If the number of keys exceeds the `capacity` from this operation, **evict** the least recently used key. **Follow up:**Could you do `get` and `put` in `O(1)` time complexity? **Example 1:** ``` Input ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"] [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]] Output [null, null, null, 1, null, -1, null, -1, 3, 4] Explanation LRUCache lRUCache = new LRUCache(2); lRUCache.put(1, 1); // cache is {1=1} lRUCache.put(2, 2); // cache is {1=1, 2=2} lRUCache.get(1); // return 1 lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3} lRUCache.get(2); // returns -1 (not found) lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3} lRUCache.get(1); // return -1 (not found) lRUCache.get(3); // return 3 lRUCache.get(4); // return 4 ``` **Constraints:** - `1 <= capacity <= 3000` - `0 <= key <= 3000` - `0 <= value <= 104` - At most `3 * 104` calls will be made to `get` and `put`. ## 题目大意 运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制 。 实现 LRUCache 类: - LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存 - int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。 - void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。 进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作? ## 解题思路 - 这一题是 LRU 经典面试题,详细解释见[第三章 LRUCache 模板](https://books.halfrost.com/leetcode/ChapterThree/LRUCache/)。 ## 代码 ```go package leetcode type LRUCache struct { head, tail *Node Keys map[int]*Node Cap int } type Node struct { Key, Val int Prev, Next *Node } func Constructor(capacity int) LRUCache { return LRUCache{Keys: make(map[int]*Node), Cap: capacity} } func (this *LRUCache) Get(key int) int { if node, ok := this.Keys[key]; ok { this.Remove(node) this.Add(node) return node.Val } return -1 } func (this *LRUCache) Put(key int, value int) { if node, ok := this.Keys[key]; ok { node.Val = value this.Remove(node) this.Add(node) return } else { node = &Node{Key: key, Val: value} this.Keys[key] = node this.Add(node) } if len(this.Keys) > this.Cap { delete(this.Keys, this.tail.Key) this.Remove(this.tail) } } func (this *LRUCache) Add(node *Node) { node.Prev = nil node.Next = this.head if this.head != nil { this.head.Prev = node } this.head = node if this.tail == nil { this.tail = node this.tail.Next = nil } } func (this *LRUCache) Remove(node *Node) { if node == this.head { this.head = node.Next node.Next = nil return } if node == this.tail { this.tail = node.Prev node.Prev.Next = nil node.Prev = nil return } node.Prev.Next = node.Next node.Next.Prev = node.Prev } ```