LC 0146 [M] LRU Cache - ALawliet/algorithms GitHub Wiki

class Node:
    def __init__(self, k, v):
        self.key = k
        self.val = v
        self.prev = None
        self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.capacity = capacity
        self.d = dict() # key to node
        # build dummy nodes and connect
        self.head = Node(-1, -1)
        self.tail = Node(-1, -1)
        self.head.next = self.tail
        self.tail.prev = self.head

    def get(self, key): # check dict, get, refresh, return
        if key in self.d:
            node = self.d[key] # got existing node
            
            # refresh this node to the most recent at DLL tail
            self.pop(node)
            self.push(node)
            
            return node.val
        
        return -1

    def put(self, key, value): # check dict, remove stale, add new
        # remove stale key first from dict
        if key in self.d:
            self.pop(self.d[key])
            
        # add it to DLL with dict
        self.push(Node(key, value)) 

    def pop(self, node): # skip over it and remove the key
        p = node.prev
        n = node.next
        p.next = n
        n.prev = p
        
        self.d.pop(node.key)

    def push(self, node): # add it to the end, add the key, make space at the front
        p = self.tail.prev
        p.next = node
        self.tail.prev = node
        node.prev = p
        node.next = self.tail
        
        self.d[node.key] = node
        
        # remove LL oldest node (after head) if out of capacity to sync with dict
        if len(self.d) > self.capacity:
            node = self.head.next
            self.pop(node)



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