【Go】LRU

55 阅读1分钟

LRU

leetcode.cn/problems/lr…

LRU题目,超级经典问题,重新复习一下,使用方法使用哈希表 + 双向链表;

涉及到很多指针的问题需要小心,其次还有封装函数成小功能,特别值得反复多练习;

type LRUCache struct {
    size int
    cap int
    cache map[int] *Node
    head, tail *Node
}

type Node struct{
    key,val int
    prev,next *Node
}

func initNode(k, v int) *Node{
    return &Node{
        key:k,
        val:v,
    }
}

func Constructor(capacity int) LRUCache {
    l := LRUCache{
        cache: map[int]*Node{},
        cap: capacity,
        head: initNode(0,0),
        tail: initNode(0,0),
    }
    l.head.next = l.tail
    l.tail.prev = l.head
    return l
}

func (this *LRUCache) Get(key int) int {
    /*将key对应的元素放到栈顶,其他元素出站*/
    
    if _, ok := this.cache[key];!ok{
        return -1
    }
    /*更新链表,把key放到最顶上*/
    curNode := this.cache[key]
    this.removeCurNode(curNode)
    this.addHead(curNode)
    return curNode.val
}

func (this *LRUCache) Put(key int, value int)  {

    if _, ok := this.cache[key]; !ok{
        // 缓存中没有,
        node := initNode(key, value)
        this.cache[key] = node
        // 把节点插入链表头
        this.addHead(node)
        this.size ++
        if this.size > this.cap{
            // 删除尾元素
            removeEle := this.removeTail()
            delete(this.cache, removeEle.key)
            this.size --
        }
    }else{
        // 缓存中存在,更新双向链表
        node := this.cache[key]
        node.val = value            // 更新值
        this.removeCurNode(node)
        this.addHead(node)
    }
}

func (this *LRUCache) removeTail() *Node{
    p := this.tail.prev
    this.removeCurNode(p)
    return p
}

func (this *LRUCache) removeCurNode(curNode *Node){
    curNode.prev.next = curNode.next
    curNode.next.prev = curNode.prev
}

func (this *LRUCache)addHead(curNode *Node){
    curNode.prev = this.head
    curNode.next = this.head.next
    this.head.next.prev = curNode
    this.head.next = curNode 
}

LFU