Skip to content

Commit eaa3506

Browse files
author
hasibulislam999
committed
LRU Cache problem solved
1 parent de439d0 commit eaa3506

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed

Doubly-Linked List/146_lru-cache.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* Title: LRU Cache
3+
* Description: Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
4+
* Author: Hasibul Islam
5+
* Date: 06/04/2023
6+
*/
7+
8+
/**
9+
* @param {number} capacity
10+
*/
11+
12+
class DoublyLinkedList {
13+
constructor() {
14+
this.head = null;
15+
this.tail = null;
16+
this.size = 0;
17+
}
18+
19+
push(key, value) {
20+
const newNode = {
21+
key,
22+
value,
23+
prev: null,
24+
next: null,
25+
};
26+
27+
if (this.head === null) {
28+
this.head = newNode;
29+
this.tail = newNode;
30+
} else {
31+
this.tail.next = newNode;
32+
newNode.prev = this.tail;
33+
this.tail = newNode;
34+
}
35+
36+
this.size++;
37+
return newNode;
38+
}
39+
40+
remove(node) {
41+
if (!node.next && !node.prev) {
42+
// if it's the only node
43+
this.head = null;
44+
this.tail = null;
45+
} else if (!node.prev) {
46+
// if it's the head
47+
this.head = node.next;
48+
this.head.prev = null;
49+
} else if (!node.next) {
50+
// if it's the tail
51+
this.tail = node.prev;
52+
this.tail.next = null;
53+
} else {
54+
// if it's in between
55+
const next = node.next;
56+
const prev = node.prev;
57+
next.prev = prev;
58+
prev.next = next;
59+
}
60+
61+
this.size--;
62+
}
63+
}
64+
65+
class LRUCache {
66+
constructor(capacity) {
67+
this.capacity = capacity;
68+
this.cache = {};
69+
this.DLL = new DoublyLinkedList();
70+
}
71+
72+
get(key) {
73+
if (!this.cache[key]) return -1;
74+
75+
const value = this.cache[key].value;
76+
this.DLL.remove(this.cache[key]);
77+
this.cache[key] = this.DLL.push(key, value);
78+
79+
return value;
80+
}
81+
82+
put(key, value) {
83+
if (this.cache[key]) this.DLL.remove(this.cache[key]);
84+
85+
this.cache[key] = this.DLL.push(key, value);
86+
87+
if (this.DLL.size > this.capacity) {
88+
const removeKey = this.DLL.head.key;
89+
this.DLL.remove(this.DLL.head);
90+
delete this.cache[removeKey];
91+
}
92+
}
93+
}

Doubly-Linked List/460_lfu-cache.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* Title: LFUCache
3+
* Description: Design and implement a data structure for a Least Frequently Used (LFU) cache.
4+
* Author: Hasibul Islam
5+
* Date: 06/04/2023
6+
*/
7+
8+
/**
9+
* @param {number} capacity
10+
*/
11+
var LFUCache = function (capacity) {
12+
this.key2countRef = new Map();
13+
this.LRUCaches = new Map();
14+
this.maxSize = capacity;
15+
this.size = 0;
16+
};
17+
18+
/**
19+
* @param {number} key
20+
* @return {number}
21+
*/
22+
LFUCache.prototype.get = function (key) {
23+
if (this.maxSize === 0) {
24+
return -1;
25+
}
26+
27+
const freq = this.key2countRef.get(key);
28+
29+
if (freq === undefined) {
30+
return -1;
31+
}
32+
33+
const prevLRUCache = this.LRUCaches.get(freq);
34+
const value = prevLRUCache.get(key);
35+
prevLRUCache.delete(key);
36+
this.key2countRef.delete(key);
37+
38+
const nextFreq = freq + 1;
39+
40+
const nextLRUCache = this.LRUCaches.get(nextFreq);
41+
this.key2countRef.set(key, nextFreq);
42+
if (nextLRUCache === undefined) {
43+
this.LRUCaches.set(nextFreq, new Map([[key, value]]));
44+
} else {
45+
nextLRUCache.set(key, value);
46+
}
47+
48+
return value;
49+
};
50+
51+
/**
52+
* @param {number} key
53+
* @param {number} value
54+
* @return {void}
55+
*/
56+
LFUCache.prototype.put = function (key, value) {
57+
if (this.maxSize === 0) {
58+
return;
59+
}
60+
61+
const freq = this.key2countRef.get(key);
62+
const nextFreq = (freq || 0) + 1;
63+
64+
if (freq) {
65+
const prevLRUCache = this.LRUCaches.get(freq);
66+
prevLRUCache.delete(key);
67+
68+
const nextLRUCaches = this.LRUCaches.get(nextFreq);
69+
this.key2countRef.set(key, nextFreq);
70+
71+
if (nextLRUCaches === undefined) {
72+
this.LRUCaches.set(nextFreq, new Map([[key, value]]));
73+
} else {
74+
nextLRUCaches.set(key, value);
75+
}
76+
} else {
77+
this.size++;
78+
79+
if (this.size > this.maxSize) {
80+
let LRUCacheForRemove = null;
81+
82+
for (let [curFreq, freqMap] of this.LRUCaches) {
83+
if (freqMap.size) {
84+
LRUCacheForRemove = freqMap;
85+
break;
86+
}
87+
}
88+
89+
const keyForRemoval = LRUCacheForRemove.keys().next().value;
90+
LRUCacheForRemove.delete(keyForRemoval);
91+
this.key2countRef.delete(keyForRemoval);
92+
this.size--;
93+
}
94+
95+
this.key2countRef.set(key, 1);
96+
const prevLRUCache = this.LRUCaches.get(nextFreq);
97+
if (prevLRUCache !== undefined) {
98+
prevLRUCache.set(key, value);
99+
} else {
100+
this.LRUCaches.set(nextFreq, new Map([[key, value]]));
101+
}
102+
}
103+
};
104+
105+
/**
106+
* Your LFUCache object will be instantiated and called as such:
107+
* var obj = new LFUCache(capacity)
108+
* var param_1 = obj.get(key)
109+
* obj.put(key,value)
110+
*/

0 commit comments

Comments
 (0)