146. LRU Cache
by Botao Xiao
Question
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. put(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.
Follow up:
- Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
Solution
- Method 1: HashMap + Bidirectional list
class LRUCache { private int capacity; private Map<Integer, DequeNode> map; private DequeNode dummy; private DequeNode tail; private int size; private static class DequeNode{ public int key; public int val; public DequeNode pre, next; public DequeNode(int key, int val){ this.key = key; this.val = val; } } public LRUCache(int capacity) { this.capacity = capacity; this.map = new HashMap<>(); this.size = 0; this.dummy = new DequeNode(-1, -1); } private void insertHead(DequeNode cur){ if(cur.pre != null){ cur.pre.next = cur.next; //remove current node from the list. if(cur.next != null) cur.next.pre = cur.pre; } DequeNode originalHead = dummy.next; //insert current node to the head of the list. cur.pre = dummy; dummy.next = cur; cur.next = originalHead; if(originalHead != null){ originalHead.pre = cur; } } public int get(int key) { if(!map.containsKey(key)) return -1; DequeNode cur = map.get(key); if(cur == tail && size != 1){ this.tail = this.tail.pre; this.tail.next = null; } insertHead(cur); return cur.val; } public void put(int key, int value) { if(map.containsKey(key)){ DequeNode cur = map.get(key); if(cur == tail && size != 1){ tail = cur.pre; } cur.val = value; insertHead(cur); }else{ DequeNode node = new DequeNode(key, value); this.map.put(key, node); if(size + 1 <= this.capacity){ if(size + 1 == 1){ this.tail = node; } insertHead(node); size++; }else{ // Need to remove the last node and insert current one. insertHead(node); DequeNode originalTail = this.tail; map.remove(originalTail.key); this.tail = this.tail.pre; this.tail.next = null; } } } } /** * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */
Subscribe via RSS