package main import ( "container/list" ) /* LRU 缓存 (Least Recently Used) 设计思路: 1. 使用一个双向链表 (list.List) + 一个哈希表 (map) 来实现。 - 双向链表保存元素的访问顺序,最新使用的放在表头,最久未使用的放在表尾。 - 哈希表用来快速定位 key 对应的链表节点,实现 O(1) 查找。 2. 每次访问 (get) 时,如果 key 存在: - 将对应的节点移到链表头部(表示最近使用过)。 - 返回节点的 value。 - 时间复杂度 O(1)。 3. 每次插入 (set) 时: - 如果 key 已存在:更新 value,并将节点移到链表头部。 - 如果 key 不存在:新建一个节点插入链表头部,并在 map 中保存 key→节点的映射。 - 插入后如果超过容量,需要删除链表尾部的节点,同时从 map 中移除对应的 key。 - 时间复杂度 O(1)。 4. 这样可以保证: - 查找、更新、插入和淘汰都在常数时间内完成。 */ type LRUElement struct { value int // 缓存的值 key int // 缓存的键,用于淘汰时从 map 中删除 } type Solution struct { linkedList *list.List // 双向链表,保存元素的访问顺序 dataMap map[int]*list.Element // 哈希表,key → 链表节点 capacity int // 缓存容量 } // Constructor 初始化 LRU 缓存,指定最大容量 func Constructor(capacity int) Solution { return Solution{ linkedList: list.New(), // 新建一个空的双向链表 dataMap: make(map[int]*list.Element), // 初始化哈希表 capacity: capacity, // 设置容量 } } // get 获取 key 对应的 value // 如果 key 存在,将对应节点移到链表头部(表示最近使用过),并返回值 // 如果 key 不存在,返回 -1 func (this *Solution) get(key int) int { if existElement, ok := this.dataMap[key]; ok { // 移动到链表头部 this.linkedList.MoveToFront(existElement) // 返回值 return existElement.Value.(*LRUElement).value } return -1 } // set 插入或更新 key-value // 如果 key 已存在,更新 value 并移到链表头部 // 如果 key 不存在,新建节点放到链表头部 // 插入后如果超过容量,淘汰链表尾部节点(最久未使用的) func (this *Solution) set(key int, value int) { // key 已存在 → 更新 value,移到头部 if existElement, ok := this.dataMap[key]; ok { existElement.Value.(*LRUElement).value = value this.linkedList.MoveToFront(existElement) return } // key 不存在 → 插入新节点到头部 elem := &LRUElement{value: value, key: key} listElem := this.linkedList.PushFront(elem) this.dataMap[key] = listElem // 如果超过容量 → 删除尾部节点 if this.linkedList.Len() > this.capacity { backElem := this.linkedList.Back() if backElem != nil { // 找到尾部元素 deleteLruElement := backElem.Value.(*LRUElement) // 从 map 中删除 delete(this.dataMap, deleteLruElement.key) // 从链表中删除 this.linkedList.Remove(backElem) } } }