g0101_0200.s0146_lru_cache.LRUCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of leetcode-in-java21 Show documentation
Show all versions of leetcode-in-java21 Show documentation
Java-based LeetCode algorithm problem solutions, regularly updated
package g0101_0200.s0146_lru_cache;
// #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Hash_Table #Design #Linked_List
// #Doubly_Linked_List #Udemy_Linked_List #Big_O_Time_O(1)_Space_O(capacity)
// #2022_06_24_Time_87_ms_(50.80%)_Space_125.2_MB_(58.73%)
import java.util.HashMap;
import java.util.Map;
public class LRUCache {
private static class LruCacheNode {
int key;
int value;
LruCacheNode prev;
LruCacheNode next;
public LruCacheNode(int k, int v) {
key = k;
value = v;
}
}
private int capacity;
private Map cacheMap = new HashMap<>();
// insert here
private LruCacheNode head;
// remove here
private LruCacheNode tail;
public LRUCache(int cap) {
capacity = cap;
}
public int get(int key) {
LruCacheNode val = cacheMap.get(key);
if (val == null) {
return -1;
}
moveToHead(val);
return val.value;
}
/*
* Scenarios :
* 1. Value key is already present.
* update
* move node to head
* 2. cache is not full
* cache is empty (create node and assign head and tail)
* cache is partially empty (add node to head and update head pointer)
* 3. cache is full
* remove node at tail, update head, tail pointers
* Recursively call put
*
*
* move node to head Scenarios
* 1. node is at head
* 2. node is at tail
* 3. node is in middle
*
*/
public void put(int key, int value) {
LruCacheNode valNode = cacheMap.get(key);
if (valNode != null) {
valNode.value = value;
moveToHead(valNode);
} else {
if (cacheMap.size() < capacity) {
if (cacheMap.size() == 0) {
LruCacheNode node = new LruCacheNode(key, value);
cacheMap.put(key, node);
head = node;
tail = node;
} else {
LruCacheNode node = new LruCacheNode(key, value);
cacheMap.put(key, node);
node.next = head;
head.prev = node;
head = node;
}
} else {
// remove from tail
LruCacheNode last = tail;
tail = last.prev;
if (tail != null) {
tail.next = null;
}
cacheMap.remove(last.key);
if (cacheMap.size() == 0) {
head = null;
}
// Call recursively
put(key, value);
}
}
}
/*
* check for 3 conditions
* 1. node is already at head
* 2. Node is tail node
* 3. Node in middle node
*/
private void moveToHead(LruCacheNode node) {
if (node == head) {
return;
}
if (node == tail) {
tail = node.prev;
}
// node is not head, it should have some valid prev node
LruCacheNode prev = node.prev;
LruCacheNode next = node.next;
prev.next = next;
if (next != null) {
next.prev = prev;
}
node.prev = null;
node.next = head;
head.prev = node;
head = node;
}
}
/*
* 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);
*/