[
design
linked list
hash table
]
Leetcode 0146 LRU Cache
Problem statement
https://leetcode.com/problems/lru-cache/
Solution
If O(1)
complexity is not required, than it is enough to keep one dictionary and one array of orders of elements, which we need to update. For O(1)
solution we can use dictionary, where we keep links to nodes of double-linked list. The idea is the following:
- Keep doubly-linked list with values - for siplicity we use looped list, where tail is connected with head.
-
Keep also dictionary, where for each value we have address of corresponding node in our linked list.
get(self, key)
will work like this: we look for our node inself.dic
, remove it from given place and put it to the end.put(self, key, value)
will work like this: first we check ifkey in self.dic
and if it is, remove it from linked list. Then we create new node, add it to the end and toself.dic
. Also if we out of capacity, we remove head and delete it fromself.dic
.
Complexity
Time complexity of all operations is O(1)
.
Code
#### borrowed code
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.dic = {}
self.head = Node(0, 0)
self.tail = Node(0, 0)
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key):
if key in self.dic:
n = self.dic[key]
self._remove(n)
self._add(n)
return n.val
return -1
def put(self, key, value):
if key in self.dic:
self._remove(self.dic[key])
n = Node(key, value)
self._add(n)
self.dic[key] = n
if len(self.dic) > self.capacity:
n = self.head.next
self._remove(n)
del self.dic[n.key]
def _remove(self, node):
p = node.prev
n = node.next
p.next = n
n.prev = p
def _add(self, node):
p = self.tail.prev
p.next = node
self.tail.prev = node
node.prev = p
node.next = self.tail