目录
LeetCode146.LRU 缓存|mid
一、题目
二、实现方法
方法一:数组存储
方法二:单链表
方法三:双向链表+哈希表
三、可直接执行代码块
持续更新...
LeetCode146.LRU 缓存|mid 一、题目
二、实现方法 方法一:数组存储请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入 *** 作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 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
1 <= capacity <= 3000
0 <= key <= 10000
0 <= value <= 105
最多调用 2 * 105 次 get 和 put
缺点:每一次都需要遍历数组修改标记
时间复杂度:O(n)
方法二:单链表缺点:顺序访问链表
时间复杂度:O(n)
方法三:双向链表+哈希表用hash表快速定位位置,
Get:在map里获取Node O(1)
Put:在map里看是否已存在,再去双链表 *** 作
时间复杂度:O(1)
q:为什么用双链表?
a:因为需要删除 *** 作,需要获取都前驱节点位置
三、可直接执行代码块从node开始构建:
type Node struct { Val int Key int Next *Node Prev *Node } func initNode(key,value int) *Node { return &Node{ Val: value, Key: key, Prev: nil, Next: nil, } } type DoublelinkedList struct { size int head,tail *Node } func initDoublelinkedList() *DoublelinkedList{ dll:=&DoublelinkedList{ size: 0, head: initNode(0,0), tail: initNode(0,0), } dll.tail.Prev=dll.head dll.head.Next=dll.tail return dll } func (this *DoublelinkedList)AddLast(x *Node){ x.Prev=this.tail.Prev x.Next=this.tail this.tail.Prev.Next=x this.tail.Prev=x this.size++ } func (this *DoublelinkedList)Remove(x *Node){ x.Prev.Next=x.Next x.Next.Prev=x.Prev x.Next=nil x.Prev=nil this.size-- } func (this *DoublelinkedList)RemoveFirst() *Node{ if this.tail.Prev==this.head { return nil } node:=this.head.Next this.Remove(node) return node } type LRUCache struct { capacity int knmp map[int]*Node cache *DoublelinkedList } func Constructor(capacity int) LRUCache{ return LRUCache{ capacity: capacity, knmp: map[int]*Node{}, cache: initDoublelinkedList(), } } func (this *LRUCache)Get(key int)int{ node,exist:=this.knmp[key] if !exist{ fmt.Println(-1) return -1 }else{ this.cache.Remove(node) this.cache.AddLast(node) fmt.Println(node.Val) return node.Val } } func (this *LRUCache)Put(key,value int){ node,exist:=this.knmp[key] newNode:=initNode(key,value) if exist{ this.cache.Remove(node) delete(this.knmp,key) }else{ if this.cache.size==this.capacity{ first:=this.cache.RemoveFirst() delete(this.knmp,first.Key) } } this.cache.AddLast(newNode) this.knmp[key]=newNode } func PrintDll(list *DoublelinkedList){ node:=list.head.Next for node!=nil{ fmt.Println(node.Val) node=node.Next } } func main() { lRUCache:=Constructor(2) lRUCache.Put(1, 1); // 缓存是 {1=1} lRUCache.Put(2, 2); // 缓存是 {1=1, 2=2} // PrintDll(lRUCache.cache) 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 }
持续更新...
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)