Skip to content

Commit 7f76d59

Browse files
committed
Updated LRU solution
1 parent caeba7d commit 7f76d59

File tree

4 files changed

+126
-28
lines changed

4 files changed

+126
-28
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package _16_25_LRU_Cache;
2+
3+
public class DoublyLinkedList {
4+
Node head = null;
5+
Node tail = null;
6+
7+
void addFirst(Node n) {
8+
if (head == null) {
9+
head = n;
10+
tail = n;
11+
} else {
12+
n.next = head;
13+
head.prev = n;
14+
head = n;
15+
}
16+
}
17+
18+
void removeLast() {
19+
removeNode(tail);
20+
// if (tail == null) {
21+
// return null;
22+
// }
23+
// if (head == tail) { // only 1 Node in List
24+
// Node n = tail;
25+
// head = null;
26+
// tail = null;
27+
// return n;
28+
// } else {
29+
// Node n = tail;
30+
// tail = n.prev;
31+
// tail.next = null;
32+
// n.prev = null;
33+
// return n;
34+
// }
35+
}
36+
37+
void removeNode(Node n) {
38+
if (n == null) {
39+
return;
40+
}
41+
if (n.prev != null) {
42+
n.prev.next = n.next;
43+
}
44+
if (n.next != null) {
45+
n.next.prev = n.prev;
46+
}
47+
if (n == head) {
48+
head = n.next;
49+
}
50+
if (n == tail) {
51+
tail = n.prev;
52+
}
53+
}
54+
}
Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,57 @@
11
package _16_25_LRU_Cache;
22

3-
import java.util.LinkedList;
3+
import java.util.Map;
44
import java.util.HashMap;
55

6-
// I have to redo this problem to decrease runtime from O(n) to O(1) (like I did in an interview - code is saved)
6+
// - Excellent explanation in Cracking the Coding Interview, 6th Edition solutions
77

8-
// To read: http://www.geeksforgeeks.org/implement-lru-cache/
8+
// FAQ
9+
//
10+
// Question: Why have our Node contain both key and value?
11+
// Answer: Because when we remove from end of Linked List, the Node's key is used
12+
// to find the Node in the HashMap (to remove the node there as well)
913

1014
class LRUCache {
11-
private final int maxSize = 7;
12-
private LinkedList<Item> items = new LinkedList<>();
13-
private HashMap<String, Item> map = new HashMap<>();
14-
15-
void add(Item item) {
16-
if (items.size() == maxSize) {
17-
map.remove(items.peekLast());
18-
items.removeLast();
15+
private int maxSize;
16+
private Map<Integer, Node> map; // gives us constant access to Nodes
17+
private DoublyLinkedList dll; // used to keep track of "freshness" of Nodes
18+
19+
public LRUCache(int maxSize) {
20+
this.maxSize = maxSize;
21+
map = new HashMap<>();
22+
dll = new DoublyLinkedList();
23+
}
24+
25+
public void add(Integer key, Node value) {
26+
if (map.containsKey(key)) {
27+
get(key);
28+
} else {
29+
if (map.size() == maxSize) {
30+
Node n = dll.tail;
31+
dll.removeLast();
32+
map.remove(n.key);
33+
}
34+
map.put(key, value);
35+
dll.addFirst(value);
1936
}
20-
items.addFirst(item);
21-
map.put(item.name, item);
2237
}
2338

24-
public Item access(String str) {
25-
Item item = map.get(str);
26-
if (item == null) {
27-
return null;
39+
public Node get(Integer key) {
40+
Node n = map.get(key);
41+
42+
// Update Freshness
43+
if (n.prev != null) {
44+
n.prev.next = n.next;
2845
}
29-
items.remove(item); // this may be O(n) instead of the O(1) that we wanted.
30-
items.addFirst(item);
31-
return item;
46+
if (n.next != null) {
47+
n.next.prev = n.prev;
48+
}
49+
dll.addFirst(n);
50+
51+
return n;
3252
}
3353

34-
public LinkedList<Item> getItems() {
35-
return items;
54+
public DoublyLinkedList getItems() {
55+
return dll;
3656
}
3757
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package _16_25_LRU_Cache;
2+
3+
public class Node {
4+
int key;
5+
String value;
6+
Node next;
7+
Node prev;
8+
9+
public Node(int k, String v) {
10+
key = k;
11+
value = v;
12+
next = null;
13+
prev = null;
14+
}
15+
16+
@Override
17+
public String toString() {
18+
return value;
19+
}
20+
}

Chp. 16 - More Problems (Moderate)/_16_25_LRU_Cache/Tester.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@ public static void main(String[] args) {
55
System.out.println("*** Test 16.25: LRU Cache\n");
66

77
/* Create LRU Cache */
8-
LRUCache cache = new LRUCache();
8+
LRUCache cache = new LRUCache(7);
99
for (int i = 20; i >= 1; i--) {
10-
Item item = new Item("Item " + i);
11-
cache.add(item);
10+
Node node = new Node(i, "Node " + i + " value");
11+
cache.add(i, node);
1212
}
1313

1414
/* Access Item 4, and print cache items */
15-
cache.access("Item 4"); // should move it to head of cache
16-
for (Item item : cache.getItems()) {
17-
System.out.println(item);
15+
cache.get(4); // should move it to head of cache
16+
DoublyLinkedList items = cache.getItems();
17+
Node head = items.head;
18+
Node n = head;
19+
while (n != null) {
20+
System.out.println(n);
21+
n = n.next;
1822
}
1923
}
2024
}

0 commit comments

Comments
 (0)