Following Solution to "LRU Cache" problem from Leetcode
Problem:
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?
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:
note: Please ignore the SOP's added for testing.
class DQueueNode {
int key;
int value;
DQueueNode next;
DQueueNode prev;
}
public class LRUCache {
int cacheSize;
int capacity;
HashMap<Integer, DQueueNode> map = new HashMap<Integer, DQueueNode>();
DQueueNode head = new DQueueNode();
DQueueNode tail = new DQueueNode();
private Integer pop(){
Integer key = tail.prev.key;
//System.out.println("Pop Tail : " + tail.prev.key);
DQueueNode node = tail.prev;
remove(node);
//System.out.println("Pop : [head : " + head.next.key + ", tail : " + tail.prev.key + "]");
return key;
}
private void add(DQueueNode node){
DQueueNode nextNode = head.next;
head.next = node;
node.prev = head;
node.next = nextNode;
nextNode.prev = node;
//System.out.println("Added : "+ node.key + ", Before [head : " + head.next.key + ", tail : " + tail.prev.key + "]");
}
private void remove(DQueueNode node){
if(node.prev != null) node.prev.next = node.next;
if(node.next != null) node.next.prev= node.prev;
//System.out.println("Removed : "+ node.key + ", Before [head : " + head.next.key + ", tail : " + tail.prev.key + "]");
}
private void moveToHead(DQueueNode node) {
// System.out.println("Move to Head : " + node.key);
// System.out.println("Before [head : " + head.next.key + ", tail : " + tail.prev.key + "]");
remove(node);
add(node);
// System.out.println("Afrer [head : " + head.next.key + ", tail : " + tail.prev.key + "]");
}
public LRUCache(int capacity) {
this.capacity = capacity;
head.next = tail;
tail.prev = head;
}
public int get(int key) {
//System.out.println("Get key :" + key );
if(map.get(key) != null){
DQueueNode node = map.get(key);
moveToHead(node);
// Put the end to the head
return node.value;
} else {
return -1;
}
}
public void put(int key, int value) {
//System.out.println("Add key :" + key + ", value : " + value);
if(map.get(key) != null){
DQueueNode node = map.get(key);
node.value = value;
map.put(key, node);
moveToHead(node);
} else {
DQueueNode node = new DQueueNode();
node.key = key;
node.value = value;
map.put(key, node);
add(node);
cacheSize++;
//System.out.println("Map Size : " + map.size());
if(cacheSize > capacity) {
Integer tailNode = pop();
//System.out.println("tail node popped : " + tailNode);
map.remove(tailNode);
cacheSize--;
//System.out.println("Removed Item from Map. cacheSize : " + cacheSize);
//System.out.println("tail : " + tail.prev.value);
}
}
//System.out.println("End Put");
}
}
/**
* 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);
*/
No comments:
Post a Comment