Skip to content

Commit 42cf89e

Browse files
refactor 146
1 parent 69549f5 commit 42cf89e

File tree

1 file changed

+115
-109
lines changed
  • src/main/java/com/fishercoder/solutions

1 file changed

+115
-109
lines changed

src/main/java/com/fishercoder/solutions/_146.java

Lines changed: 115 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -34,132 +34,138 @@ Could you do both operations in O(1) time complexity?
3434
public class _146 {
3535

3636
public class Solution1 {
37-
/**
38-
* The shortest implementation is to use LinkedHashMap:
39-
* specify a size of the linkedHashMap;
40-
* override the removeEldestEntry method when its size exceeds max size:
41-
* https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html#removeEldestEntry-java.util.Map.Entry-
42-
* in the constructor, set the last boolean variable to be true: it means the ordering mode,
43-
* if we set it to be true, it means in access order, false, means it's in insertion order:
44-
* https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html#LinkedHashMap-int-float-boolean-
45-
*/
46-
47-
private Map<Integer, Integer> cache;
48-
private final int max;
49-
50-
public Solution1(int capacity) {
51-
max = capacity;
52-
cache = new LinkedHashMap<Integer, Integer>(capacity, 1.0f, true) {
53-
public boolean removeEldestEntry(Map.Entry eldest) {
54-
return cache.size() > max;
55-
}
56-
};
57-
}
37+
public class LRUCache {
38+
/**
39+
* The shortest implementation is to use LinkedHashMap:
40+
* specify a size of the linkedHashMap;
41+
* override the removeEldestEntry method when its size exceeds max size:
42+
* https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html#removeEldestEntry-java.util.Map.Entry-
43+
* in the constructor, set the last boolean variable to be true: it means the ordering mode,
44+
* if we set it to be true, it means in access order, false, means it's in insertion order:
45+
* https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html#LinkedHashMap-int-float-boolean-
46+
*/
47+
48+
private Map<Integer, Integer> cache;
49+
private final int max;
50+
51+
public LRUCache(int capacity) {
52+
max = capacity;
53+
cache = new LinkedHashMap<Integer, Integer>(capacity, 1.0f, true) {
54+
public boolean removeEldestEntry(Map.Entry eldest) {
55+
return cache.size() > max;
56+
}
57+
};
58+
}
5859

59-
public int get(int key) {
60-
return cache.getOrDefault(key, -1);
61-
}
60+
public int get(int key) {
61+
return cache.getOrDefault(key, -1);
62+
}
6263

63-
public void set(int key, int value) {
64-
cache.put(key, value);
64+
public void set(int key, int value) {
65+
cache.put(key, value);
66+
}
6567
}
6668
}
6769

6870
public class Solution2 {
69-
/**The more verbose solution is to write a doubly linked list plus a map.*/
70-
private class Node {
71-
int key;
72-
int value;
73-
74-
Solution2.Node prev;
75-
Solution2.Node next;
71+
public class LRUCache {
72+
/**
73+
* The more verbose solution is to write a doubly linked list plus a map.
74+
*/
75+
private class Node {
76+
int key;
77+
int value;
78+
79+
LRUCache.Node prev;
80+
LRUCache.Node next;
81+
82+
Node(int k, int v) {
83+
this.key = k;
84+
this.value = v;
85+
}
7686

77-
Node(int k, int v) {
78-
this.key = k;
79-
this.value = v;
87+
Node() {
88+
this.key = 0;
89+
this.value = 0;
90+
}
8091
}
8192

82-
Node() {
83-
this.key = 0;
84-
this.value = 0;
93+
private int capacity;
94+
private int count;
95+
private LRUCache.Node head;
96+
private LRUCache.Node tail;
97+
private Map<Integer, LRUCache.Node> map;
98+
// ATTN: the value should be Node type! This is the whole point of having a class called Node!
99+
100+
public LRUCache(int capacity) {
101+
this.capacity = capacity;
102+
this.count = 0;// we need a count to keep track of the number of elements in the cache so
103+
// that we know when to evict the LRU one from the cache
104+
this.map = new HashMap();
105+
head = new LRUCache.Node();
106+
tail = new LRUCache.Node();
107+
head.next = tail;
108+
tail.prev = head;
85109
}
86-
}
87-
88-
private int capacity;
89-
private int count;
90-
private Solution2.Node head;
91-
private Solution2.Node tail;
92-
private Map<Integer, Solution2.Node> map;
93-
// ATTN: the value should be Node type! This is the whole point of having a class called Node!
94-
95-
public Solution2(int capacity) {
96-
this.capacity = capacity;
97-
this.count = 0;// we need a count to keep track of the number of elements in the cache so
98-
// that we know when to evict the LRU one from the cache
99-
this.map = new HashMap();
100-
head = new Solution2.Node();
101-
tail = new Solution2.Node();
102-
head.next = tail;
103-
tail.prev = head;
104-
}
105110

106-
public int get(int key) {
107-
Solution2.Node node = map.get(key);
108-
// HashMap allows value to be null, this is superior than HashTable!
109-
if (node == null) {
110-
return -1;
111-
} else {
112-
113-
/**Do two operations: this makes the process more clear:
114-
* remove the old node first, and then
115-
* just add the node again.
116-
* This will guarantee that this node will be at the latest position:
117-
* the most recently used position.*/
118-
remove(node);
119-
add(node);
120-
121-
return node.value;
111+
public int get(int key) {
112+
LRUCache.Node node = map.get(key);
113+
// HashMap allows value to be null, this is superior than HashTable!
114+
if (node == null) {
115+
return -1;
116+
} else {
117+
118+
/**Do two operations: this makes the process more clear:
119+
* remove the old node first, and then
120+
* just add the node again.
121+
* This will guarantee that this node will be at the latest position:
122+
* the most recently used position.*/
123+
remove(node);
124+
add(node);
125+
126+
return node.value;
127+
}
122128
}
123-
}
124129

125-
public void set(int key, int value) {
126-
Solution2.Node node = map.get(key);
127-
if (node == null) {
128-
node = new Solution2.Node(key, value);
129-
map.put(key, node);
130-
add(node);
131-
count++;
132-
133-
if (count > capacity) {
134-
/** ATTN: It's tail.prev, not tail, because tail is always an invalid node, it
135-
doesn't contain anything, it's always the tail.prev that is the last node in the
136-
cache*/
137-
Solution2.Node toDelete = tail.prev;
138-
map.remove(toDelete.key);
139-
remove(toDelete);
140-
count--;
130+
public void set(int key, int value) {
131+
LRUCache.Node node = map.get(key);
132+
if (node == null) {
133+
node = new LRUCache.Node(key, value);
134+
map.put(key, node);
135+
add(node);
136+
count++;
137+
138+
if (count > capacity) {
139+
/** ATTN: It's tail.prev, not tail, because tail is always an invalid node, it
140+
doesn't contain anything, it's always the tail.prev that is the last node in the
141+
cache*/
142+
LRUCache.Node toDelete = tail.prev;
143+
map.remove(toDelete.key);
144+
remove(toDelete);
145+
count--;
146+
}
147+
} else {
148+
remove(node);
149+
node.value = value;
150+
add(node);
141151
}
142-
} else {
143-
remove(node);
144-
node.value = value;
145-
add(node);
146152
}
147-
}
148153

149-
private void remove(Solution2.Node node) {
150-
Solution2.Node next = node.next;
151-
Solution2.Node prev = node.prev;
152-
prev.next = next;
153-
next.prev = prev;
154-
}
154+
private void remove(LRUCache.Node node) {
155+
LRUCache.Node next = node.next;
156+
LRUCache.Node prev = node.prev;
157+
prev.next = next;
158+
next.prev = prev;
159+
}
155160

156-
private void add(Solution2.Node node) {
157-
// ATTN: we'll always add the node into the first position: head.next!!!!
158-
Solution2.Node next = head.next;
159-
head.next = node;
160-
node.next = next;
161-
node.prev = head;
162-
next.prev = node;
161+
private void add(LRUCache.Node node) {
162+
// ATTN: we'll always add the node into the first position: head.next!!!!
163+
LRUCache.Node next = head.next;
164+
head.next = node;
165+
node.next = next;
166+
node.prev = head;
167+
next.prev = node;
168+
}
163169
}
164170
}
165171
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy