Skip to content

Commit 9b555d6

Browse files
Problem 146 (#31)
* WIP solution still failing * add pseudocode, solution and update README
1 parent dbdbdef commit 9b555d6

File tree

2 files changed

+128
-1
lines changed

2 files changed

+128
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ As I work through this list I figure I would make a GitHub repo with my solution
7373
62. Find All Anagrams in a String #438
7474
63. Minimum Height Trees #310
7575
64. Task Scheduler #621
76-
65. **LRU Cache #146**
76+
65. [LRU Cache #146](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/lru-cache-146.md)
7777
66. Kth Smallest Element in a BST #230
7878

7979
### Hard
@@ -134,6 +134,7 @@ In order to practice with similar data structures I'll be placing each problem i
134134
- [Linked List Cycle #141](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/linked-list-cycle-141.md)
135135
- [Reverse Linked List #206](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/reverse-linked-list-206.md)
136136
- [Middle of the Linked List #876](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/middle-linked-list-876.md)
137+
- [LRU Cache #146](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/lru-cache-146.md)
137138

138139
### Hash Table
139140

@@ -149,6 +150,7 @@ In order to practice with similar data structures I'll be placing each problem i
149150
- [Longest Substring Without Repeating Characters #3](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/longest-substring-3.md)
150151
- [3Sum #15](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/3Sum-15.md)
151152
- [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
153+
- [LRU Cache #146](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/lru-cache-146.md)
152154

153155
### Binary Tree
154156

medium/lru-cache-146.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# LRU Cache
2+
3+
Page on leetcode: https://leetcode.com/problems/lru-cache/
4+
5+
## Problem Statement
6+
7+
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
8+
9+
Implement the LRUCache class:
10+
11+
- LRUCache(int capacity) Initialize the LRU cache with positive size capacity.
12+
- int get(int key) Return the value of the key if the key exists, otherwise return -1.
13+
- 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.
14+
15+
The functions get and put must each run in O(1) average time complexity.
16+
17+
### Constraints
18+
19+
- 1 <= capacity <= 3000
20+
- 0 <= key <= 104
21+
- 0 <= value <= 105
22+
- At most 2 \* 105 calls will be made to get and put.
23+
24+
### Example
25+
26+
```
27+
Input
28+
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
29+
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
30+
Output
31+
[null, null, null, 1, null, -1, null, -1, 3, 4]
32+
33+
Explanation
34+
LRUCache lRUCache = new LRUCache(2);
35+
lRUCache.put(1, 1); // cache is {1=1}
36+
lRUCache.put(2, 2); // cache is {1=1, 2=2}
37+
lRUCache.get(1); // return 1
38+
lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}
39+
lRUCache.get(2); // returns -1 (not found)
40+
lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}
41+
lRUCache.get(1); // return -1 (not found)
42+
lRUCache.get(3); // return 3
43+
lRUCache.get(4); // return 4
44+
```
45+
46+
## Solution
47+
48+
### Initial Thoughts
49+
50+
- get and put time complexity of O(1) suggest hashmap and maybe a stack
51+
- least recently used suggest some sort, based on a counter
52+
- If I used purely a stack put would be O(1), get would be O(n)
53+
54+
### Optimized Solution
55+
56+
You can see an explanation of the solution here: https://www.youtube.com/watch?v=7ABFKPK2hD4
57+
58+
#### Psuedocode
59+
60+
1. Create a Node class for creating a doubly linked list
61+
2. Create LRUCache class with two dummy nodes (old and recent), the capacity and a hashmap for the cache
62+
3. Create get method, removes then inserts node from list and returns if it exist, otherwise returns -1
63+
4. Create put method, removes node from list if exist, updates cache value, inserts into list
64+
65+
- If cache size is too big, removes oldest node from list and deletes from cache
66+
67+
5. Create remove helper method, takes out a node from list and reconnects adjacent pointers
68+
6. Create insert helper method, inserts node between "recent" dummy node and next node in list
69+
70+
```javascript
71+
const Node = function (key, val) {
72+
this.key = key;
73+
this.val = val;
74+
this.prev = null;
75+
this.next = null;
76+
};
77+
78+
const LRUCache = function (capacity) {
79+
this.cap = capacity;
80+
this.cache = new Map();
81+
this.old = new Node('old', 0);
82+
this.recent = new Node('recent', 0);
83+
this.old.next = this.recent;
84+
this.recent.prev = this.old;
85+
};
86+
87+
LRUCache.prototype.remove = function (node) {
88+
prev = node.prev;
89+
nxt = node.next;
90+
prev.next = nxt;
91+
nxt.prev = prev;
92+
};
93+
94+
LRUCache.prototype.insert = function (node) {
95+
prev = this.recent.prev;
96+
nxt = this.recent;
97+
prev.next = node;
98+
nxt.prev = node;
99+
node.next = nxt;
100+
node.prev = prev;
101+
};
102+
103+
LRUCache.prototype.get = function (key) {
104+
if (this.cache.has(key)) {
105+
this.remove(this.cache.get(key));
106+
this.insert(this.cache.get(key));
107+
return this.cache.get(key).val;
108+
}
109+
return -1;
110+
};
111+
112+
LRUCache.prototype.put = function (key, value) {
113+
if (this.cache.has(key)) {
114+
this.remove(this.cache.get(key));
115+
}
116+
this.cache.set(key, new Node(key, value));
117+
this.insert(this.cache.get(key));
118+
119+
if (this.cache.size > this.cap) {
120+
const lru = this.old.next;
121+
this.remove(lru);
122+
this.cache.delete(lru.key);
123+
}
124+
};
125+
```

0 commit comments

Comments
 (0)