Lru Cache
To solve this coding challenge of designing and implementing an LRU (Least Recently Used) cache, you'll need to create a data structure that adheres to specific constraints: it must store key-value pairs, offer O(1) average time complexity for both retrieving a value from the cache and inserting a new key-value pair, and manage the size of the cache such that it does not exceed a defined capacity. If the cacheβs size exceeds this capacity constraint, it must remove the least recently used (LRU) item before adding a new key-value pair.
and
operations run in O(1) average time complexity, adhering to the constraints of the problem.
Explanation
The LRU Cache is essential for scenarios where we need quick access to frequently accessed data but within a capacity limit. To manage the cache efficiently, we need an underlying data structure that supports fast look-up, add, and delete operations (hash table) and another one to keep track of the access order (doubly linked list).Key Points:
- Hash Table : Allows us to store key-value pairs for quick access.
- Doubly Linked List : Keeps track of the order in which keys are accessed, with the most recently accessed key moving to the front and the least recently accessed one moving to the end. This property is crucial for determining which key to evict when the cache exceeds its capacity.
- Capacity Handling : Ensures that once the cache reaches its capacity, the least recently used item is removed to make space for new entries.
- Check if the key exists in the cache.
- If it does, update its position to reflect a recent access.
- Return the value.
- If the key doesnβt exist, return -1.
- If the key already exists, just update its value and reorder it as most recently used.
- If the key does not exist:
- Check if the current cache size is at capacity.
- If it is, remove the least recently used item (the first item in the key order list).
- Insert the new key-value pair and update the order list.
- Initialization (LRUCache with capacity) :
-
You initialize your cache with a given capacity. An empty dictionary (
self.cache
self.key_order
-
Get Method (
get(key)
- Check Existence : Use the dictionary to quickly check if the key exists.
-
Update Order
: If the key exists, to mark it as recently used, you remove it from its current position in
self.key_order
- Return Value : Return the value from the dictionary. If the key does not exist, return -1.
-
Put Method (
put(key, value)
- Check Existence : If the key exists already, update its position to the end of the order list and update its value in the dictionary.
- Capacity Management : If adding this new key-value pair would exceed the cacheβs capacity:
-
Remove the least recently used item (the first item in
self.key_order
- Delete this item from the dictionary.
-
Insert New Value
: Add the new key-value pair to the dictionary and mark it as recently used by appending it to the end of
self.key_order
Pseudocode Details:
Here is the detailed step-by-step pseudocode explanation along with the pseudocode itself.Pseudocode Structure and Detailed Steps:
Initialization:
When initializing, we need to maintain the capacity and the data structure for the cache.
# LRUCache class initialization
initialize LRUCache with capacity:
set self.capacity to the given capacity # Store the maximum size of the cache
create an empty dictionary self.cache # To store key-value pairs
create an empty list self.key_order # To keep track of the usage order of keys
Get Method:
To retrieve a value based on the key:
# Method to fetch data by key
method get(key):
if key exists in self.cache: # Check if the key is in the cache
remove key from self.key_order # This updates the key's position in the order
append key to the end of self.key_order # Place key at the end to mark it as recently used
return value corresponding to key from self.cache # Return the cached value
else:
return -1 # Key doesn't exist in cache
Put Method:
To insert or update key-value pairs:
# Method to insert or update key-value pairs
method put(key, value):
if key exists in self.cache: # Check if the key is already in the cache
remove key from self.key_order # Remove key from its current position
elif length of self.cache equals self.capacity: # If cache size has reached capacity
LRU_key = remove the first item from self.key_order # Identify and remove the oldest key
delete LRU_key from self.cache # Remove LRU key from the cache
insert (key, value) into self.cache # Insert the new key-value pair
append key to the end of self.key_order # Place the key at the end to mark it as recently used
Step-by-Step Explanation:
get
put