LRU Cache

Design and implement a data structure forLeast Recently Used (LRU) cache. It should support the following operations:getandput.

get(key)- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. put(key, value)- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Follow up: Could you do both operations inO(1)time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

分析

一直错的:

get 不记得删除链表的旧位置:

dict只有拿node的作用,只有满删, list存在就删

一个双链表和一个dict.自建一个LRUNode class

链表删除在原地做简单,直接原地做。链表插入尾部写成函数

LL remove cur and insert cur

set:

    # 1 dict 有:更新node值, LL remove cur and insert cur
    # 2 超过容量:去dict 里head, 去LL head 腾位置
    # 3 dict 无:建新Node, dict insert and LL insert cur(new)
import collections


class LRUNode:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None


class LRUCache:

    # 基本元素 1dict 2双链表 3 头尾指针,还要记得互指
    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.capacity = capacity
        self.dict = collections.defaultdict(LRUNode)
        self.head = LRUNode(0, 0)
        self.tail = LRUNode(0, 0)
        self.head.next = self.tail
        self.tail.prev = self.head

    # LL removecur and insert cur
    def get(self, key):
        """
        :type key: int
        :rtype: int
        """
        # update LL: remove cur and insert cur
        if key not in self.dict:
            return -1
        node = self.dict[key]
        # remove cur
        node.prev.next = node.next
        node.next.prev = node.prev
        # insert cur
        self.insertLL(node)

        return node.value

    # 1 dict 有:更新node值, LL remove cur and insert cur
    # 2 超过容量:去dict 里head, 去LL head 腾位置
    # 3 dict 无:建新Node, dict insert and LL insert cur(new)
    def put(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: void
        """
        if key in self.dict:
            self.dict[key].value = value  # update node's value
            self.get(key)  # update LL cur
            return

        # make space for new node first
        #唯一一处删dict
        if len(self.dict) == self.capacity:
            node = self.head.next
            del self.dict[node.key]
            self.head.next = node.next
            node.next.prev = self.head

        newNode = LRUNode(key, value)
        self.dict[key] = newNode
        self.insertLL(newNode)

    # LL insert node
    def insertLL(self, node):
        # prevs then nexts
        node.prev = self.tail.prev
        self.tail.prev = node
        node.prev.next = node
        node.next = self.tail

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

Python

class Node:
    def __init__(self,key,value):
        self.key = key
        self.value = value
        self.pre = None
        self.next = None
        
class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.nodeMap = {}
        self.head = Node(-1,-1)
        self.tail = Node(-1,-1)
        self.head.next = self.tail
        self.tail.pre = self.head
        
    def moveToTail(self, key:int) -> None:
        node = self.nodeMap[key]
        self.tail.pre.next = node
        node.pre = self.tail.pre
        node.next = self.tail
        self.tail.pre = node
        
    def get(self, key: int) -> int:
        if key not in self.nodeMap:
            return -1
        node = self.nodeMap[key]
        #要去掉当前点位置
        node.pre.next = node.next
        node.next.pre = node.pre
        #新位置尾部加入当前点
        self.moveToTail(key)
        return node.value
        

    def put(self, key: int, value: int) -> None:
        node = None
        #有的话: 1:node更新value 2: list更新位置
        if key in self.nodeMap:            
            node = self.nodeMap[key]
            node.value = value
            self.get(key)
        else:#没有的话 1建Node 2 list加入新位置,尾部 3 检查是否需要更新dict。(一般都是有加入就有去除。
            #唯一改dict的地方,别处都是用dict取node而已。
            if self.capacity == len(self.nodeMap):
                self.nodeMap.pop(self.head.next.key) #dict里去掉元素,错了
                #去掉头元素
                self.head.next = self.head.next.next
                self.head.next.pre = self.head
            node = Node(key,value)
            self.nodeMap[key] = node
            self.moveToTail(key)#新元素加入尾部。
        
        


# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

Python OrderedDict

move_to_end()

popitem(last=False)去掉头部的元素,在capacity超过时候使用。

```python
from collections import OrderedDict
class LRUCache:
    """
    @param: capacity: An integer
    """
    def __init__(self, capacity):
        # do intialization if necessary
        self.capacity = capacity
        self.cache = OrderedDict()

    """
    @param: key: An integer
    @return: An integer
    """
    def get(self, key):
        # write your code here       
        if key not in self.cache:
            return -1
        self.cache.move_to_end(key)
        return self.cache.get(key)          

    """
    @param: key: An integer
    @param: value: An integer
    @return: nothing
    """
    def set(self, key, value):
        # write your code here
        self.cache[key] = value
        if len(self.cache)  > self.capacity:
            self.cache.popitem(last=False)
        self.cache.move_to_end(key)

```

Last updated