@@ -34,132 +34,138 @@ Could you do both operations in O(1) time complexity?
34
34
public class _146 {
35
35
36
36
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
+ }
58
59
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
+ }
62
63
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
+ }
65
67
}
66
68
}
67
69
68
70
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
+ }
76
86
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
+ }
80
91
}
81
92
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 ;
85
109
}
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
- }
105
110
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
+ }
122
128
}
123
- }
124
129
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 );
141
151
}
142
- } else {
143
- remove (node );
144
- node .value = value ;
145
- add (node );
146
152
}
147
- }
148
153
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
+ }
155
160
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
+ }
163
169
}
164
170
}
165
171
}
0 commit comments