146.LRU 缓存

147 阅读1分钟

题目:
请你设计并实现一个满足  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) 的平均时间复杂度运行。
解法:
双向链表+hash表

type LRUCache struct {
	Cache map[int]*LinkNode
	Link *LinkNode
	Head *LinkNode
	Capacity int
	
}

type LinkNode struct {
	Pre *LinkNode
	Next *LinkNode
	Val int
	Key int
	
}

func Constructor(capacity int) LRUCache {
	return LRUCache{
		Cache: make(map[int]*LinkNode),
		// LinkDummyHead: &LinkNode{},
		Capacity: capacity,
	}
}


func (this *LRUCache) Get(key int) int {
	if node, ok := this.Cache[key]; ok {
		this.MoveToHead(node)
        // fmt.Println("get",key)
		return node.Val
	}
	return -1
}


func (this *LRUCache) Put(key int, value int)  {
	if node, ok := this.Cache[key]; ok {
		node.Val = value
		this.MoveToHead(node)
        // fmt.Println("put",key, value)
	} else {
		nd := &LinkNode{Key:key, Val:value}
		if len(this.Cache) == 0 {
			nd.Pre = nd
			nd.Next = nd
			this.Head = nd
		} else if len(this.Cache) == this.Capacity {
			this.AddToHead(nd)	
            nKey := this.RemoveTail()
            delete(this.Cache, nKey)
		} else {
			this.AddToHead(nd)	
		}
		
		this.Cache[key] = nd
	}

}

func (this *LRUCache) AddToHead(node *LinkNode)  {
		head := this.Head
		headPre := head.Pre
		headPre.Next = node

		node.Next = head
		node.Pre = headPre

		head.Pre = node
		this.Head = node

}

func (this *LRUCache) RemoveTail()  int {
    head := this.Head
	tail := head.Pre
	tailPre := tail.Pre


    tailPre.Next = head
    head.Pre = tailPre 
 
	return tail.Key
}

// node移动到头节点
func (this *LRUCache) MoveToHead(node *LinkNode) {
    // 这里如果不这样处理会有问题,head节点会被摘掉
    if this.Head == node {
        return
    }
    // 摘除node节点
    nodePre := node.Pre
    nodeNext := node.Next
    nodePre.Next = nodeNext
    nodeNext.Pre = nodePre

    // node节点移动到head
    tail := this.Head.Pre 
    head := this.Head 
    tail.Next = node
    head.Pre = node
    node.Pre = tail
    node.Next = head
    this.Head = node

//    fmt.Printf("MoveToHead head:%+v, tail:%+v\n", *head, *tail)
}