1
+ class LFUCache {
2
+ class Node {
3
+ int key , val ;
4
+ Node prev , next ;
5
+ int cnt ;
6
+ public Node (int k , int v ) {
7
+ this .key = k ;
8
+ this .val = v ;
9
+ cnt = 1 ;
10
+ }
11
+ }
12
+
13
+ class DLL {
14
+ Node head , tail ;
15
+ int len ;
16
+ public DLL () {
17
+ head = new Node (0 ,0 );
18
+ tail = new Node (0 , 0 );
19
+ head .next = tail ;
20
+ tail .prev = head ;
21
+ len = 0 ; // since no node in DLL
22
+ }
23
+
24
+ public void addHead (Node node ) {
25
+ Node next = head .next ; // save next address
26
+ head .next = node ;
27
+ node .prev = head ;
28
+ node .next = next ;
29
+ next .prev = node ;
30
+ map .put (node .key , node );
31
+ len ++;
32
+ }
33
+
34
+ public void remove (Node node ) {
35
+ Node prev = node .prev ; // save prev address
36
+ Node next = node .next ;
37
+ prev .next = next ;
38
+ next .prev = prev ;
39
+ map .remove (node .key );
40
+ len --;
41
+ }
42
+
43
+ public void removeTail () {
44
+ Node prevTail = tail .prev ;
45
+ remove (prevTail );
46
+ }
47
+ }
48
+ Map <Integer , DLL > freq ;
49
+ Map <Integer , Node > map ; // for (key, node) pair
50
+ int capacity , size ;
51
+ int maxFreq ;
52
+ public LFUCache (int capacity ) {
53
+ freq = new HashMap <>();
54
+ map = new HashMap <>();
55
+ this .capacity = capacity ;
56
+ size = 0 ;
57
+ maxFreq = 0 ;
58
+ }
59
+
60
+ public int get (int key ) {
61
+ if (map .get (key ) == null ) return -1 ;
62
+ Node node = map .get (key );
63
+ int prevFreq = node .cnt ;
64
+ DLL prevList = freq .get (prevFreq );
65
+ prevList .remove (node );
66
+ int curFreq = prevFreq + 1 ;
67
+ maxFreq = Math .max (maxFreq , curFreq );
68
+ DLL curList = freq .getOrDefault (curFreq , new DLL ()); // since there may not be a DLL on that frequency
69
+ node .cnt ++;
70
+ curList .addHead (node );
71
+ freq .put (prevFreq , prevList ); // updating prevfreq list and curfreq list
72
+ freq .put (curFreq , curList );
73
+ return node .val ;
74
+ }
75
+
76
+ public void put (int key , int value ) {
77
+ if (capacity == 0 ) return ; // we can't put
78
+ if (map .get (key ) != null ) { // meaning a node exists
79
+ map .get (key ).val = value ; //update its value
80
+ get (key ); // since we are accessing it, we have to increase it's freq
81
+ return ;
82
+ }
83
+ Node newNode = new Node (key , value );
84
+ DLL curList = freq .getOrDefault (1 , new DLL ()); // get the DLL corresponding to freq 1 or create a new one
85
+ curList .addHead (newNode );
86
+ size ++;
87
+ if (size > capacity ) {
88
+ if (curList .len > 1 ) { // if freq 1 list has nodes in it, remove last one
89
+ curList .removeTail ();
90
+ } else {
91
+ for (int i =2 ; i <=maxFreq ; i ++) {
92
+ if (freq .get (i ) != null && freq .get (i ).len > 0 ) {
93
+ freq .get (i ).removeTail ();
94
+ break ;
95
+ }
96
+ }
97
+ }
98
+ size --;
99
+ }
100
+ freq .put (1 , curList );
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Your LFUCache object will be instantiated and called as such:
106
+ * LFUCache obj = new LFUCache(capacity);
107
+ * int param_1 = obj.get(key);
108
+ * obj.put(key,value);
109
+ */
0 commit comments