- LRU Cache = LC: 146
Have Practiced: 0
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(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.
class LinkedNode:
def __init__(self, key=None, value=None, next=None):
self.key = key
self.value = value
self.next = next
class LRUCache:
"""
@param: capacity: An integer
"""
def __init__(self, capacity):
self.hash = {}
self.head = LinkedNode() # dummy
self.tail = self.head
self.capacity = capacity
# change "head -> node1 -> node2"
# to "head -> node1 -> node2 -> node3"
def push_back(self, node):
self.hash[node.key] = self.tail
self.tail.next = node
self.tail = node
# change "head -> node1 -> node2 -> node3"
# to "head -> node2 -> node3"
def pop_front(self,):
del self.hash[self.head.next.key] # delete a reference, not node
self.hash[self.head.next.next.key] = self.head
self.head.next = self.head.next.next
# change "head -> node -> node2"
# to "head -> node2 -> node"
def move_to_back(self, prev):
node = prev.next
if node == self.tail:
return
prev.next = node.next
self.hash[node.next.key] = prev
node.next = None
self.push_back(node)
"""
@param: key: An integer
@return: An integer
"""
def get(self, key):
if key in self.hash:
self.move_to_back(self.hash[key])
return self.hash[key].next.value
return -1
"""
@param: key: An integer
@param: value: An integer
@return: nothing
"""
def set(self, key, value):
if key in self.hash:
self.move_to_back(self.hash[key])
self.hash[key].next.value = value
else:
self.push_back(LinkedNode(key, value))
if len(self.hash) > self.capacity:
self.pop_front()
Time: O(1)
for all
Space: ``
Notes:
- I need to understand WHAT is LRU cache:
Least Recently Used - The data you visited in the last round, you will very probably visit it in the next round. - Use linked list in this problem, because I want to have
pop_front()
,push_back()
andmove_to_back()
.- Linked list takes least time,
O(1)
, but not formove_to_back()
. Therefore, usehash map(cache key, linked list node)
to look up nodes inO(1)
time - If I need to remove a node, I need to know its prev node. Therefore,
Doubly linked list
is needed. Or, usehash map(cache key, prev node)
instead. Hash map works 1) adding another property of linked, prev. 2) easy to edit value of node.
- Linked list takes least time,
- Learn to write
LinkedNode()
in Python.
Remember to initialize all values to beNone
def __init__(self, key=None, value=None, next=None):
- Relate this problem to First Unique Character in a String. A follow-up of this problem is data stream.
Extension:
- Python Tricks, use
OrderedDict
which has the same concept. Similar to LinkedHashMap in Java.
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.cache = OrderedDict()
def get(self, key):
if key not in self.cache:
return -1
value = self.cache.pop(key) # take it out
self.cache[key] = value # insert it back
return value
def set(self, key, value):
if key in self.cache:
self.cache.pop(key)
elif len(self.cache) == self.capacity:
## last = True => FILO
## last = False => FIFO
self.cache.popitem(last = False) # just pop head or tail, no key input
self.cache[key] = value
网友评论