目录
LeetCode146.LRU 缓存|mid
一、题目
二、实现方法
方法一:数组存储
缺点:每一次都需要遍历数组修改标记
时间复杂度: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
}