146. LRU Cache
Problem
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
Implement the LRUCache class:
- LRUCache(int capacity) Initialize the LRU cache with positive size capacity.
- int get(int key) Return the value of the key if the key exists, otherwise return -1.
- void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.
The functions get and put must each run in O(1) average time complexity.
Example 1:
Constraints:
- 1 <= capacity <= 3000
- 0 <= key <= 104
- 0 <= value <= 105
- At most 2 * 105 calls will be made to get and put.
Approach
To solve this problem optimally, we can use a doubly linked list in which we keep track of the left and right (head and tail) of the list for our LRU and MRU (most recently used), respectively.
Since we want O(1) retrieval, we'll use a hash map to store the keys alongside a pointer to a node in the list where the key and value will be stored.
When we retrieve an element, we want to update our list to reflect that the retrieval is now the MRU so what we do is remove that specific node from the list and then re-insert at the right (tail) for it to become the MRU.
When we want to insert an element, we create a new node for our list, insert it at the right (MRU). Then, we check if our capacity has been exceeded and remove the node at the left (LRU) and delete the corresponding key from the hashmap.
Complexity
Time: O(1)
Removing and inserting into the list when we have pointers for the head and tail is constant.
Space: O(cap)
We create a hashmap and a doubly linked list that will have a maximum size of capacity.