146. 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)
的平均时间复杂度运行。
哈希表 + 双向链表
顾名思义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
| type Node struct {
Key, Val int
Next *Node
Prev *Node
}
type LinkList struct {
Head, Tail *Node
}
func NewLinkList() *LinkList {
res := LinkList{Head: &Node{}, Tail: &Node{}}
res.Head.Next = res.Tail
res.Tail.Prev = res.Head
return &res
}
func (l *LinkList) AddToHead(n *Node) {
l.Head.Next.Prev = n
n.Next = l.Head.Next
l.Head.Next = n
n.Prev = l.Head
}
func (l *LinkList) MoveToHead(n *Node) {
n.Prev.Next = n.Next
n.Next.Prev = n.Prev
l.Head.Next.Prev = n
n.Next = l.Head.Next
l.Head.Next = n
n.Prev = l.Head
}
func (l *LinkList) RemoveTail() int {
n := l.Tail.Prev
l.Tail.Prev = n.Prev
n.Prev.Next = l.Tail
return n.Key
}
type LRUCache struct {
HashMap map[int]*Node
LinkList *LinkList
Capacity int
Size int
}
func Constructor(capacity int) LRUCache {
res := LRUCache{HashMap: make(map[int]*Node), LinkList: NewLinkList()}
return res
}
func (this *LRUCache) Get(key int) int {
if _, ok := this.HashMap[key]; !ok {
return -1
} else {
node := this.HashMap[key]
// 命中,移至最前
this.LinkList.MoveToHead(node)
return node.Val
}
}
func (this *LRUCache) Put(key int, value int) {
if _, ok := this.HashMap[key]; !ok {
// 不存在
node := Node{Key: key, Val: value}
this.HashMap[key] = &node
this.LinkList.AddToHead(&node)
this.Size++
if this.Size > this.Capacity {
// 溢出,淘汰最末
removedKey := this.LinkList.RemoveTail()
delete(this.HashMap, removedKey)
this.Size--
}
} else {
// 存在,修改其值
node := this.HashMap[key]
node.Val = value
// 命中,移至最前
this.LinkList.MoveToHead(node)
}
}
|