1
+ // https://leetcode.com/problems/lfu-cache/
2
+
3
+ class ListNode {
4
+ constructor ( val , next , prev ) {
5
+ this . val = ( val === undefined ? 0 : val )
6
+ this . next = ( next === undefined ? null : next )
7
+ this . prev = ( next === undefined ? null : prev )
8
+ }
9
+ }
10
+
11
+ class LinkedList {
12
+ constructor ( ) {
13
+ this . map = new Map ( )
14
+ this . Right = new ListNode ( null )
15
+ this . Left = new ListNode ( null , this . Right )
16
+ this . Right . prev = this . Left
17
+ }
18
+
19
+ len ( ) {
20
+ return this . map . size
21
+ }
22
+
23
+ pop ( val ) {
24
+ if ( this . map . has ( val ) ) {
25
+ let node = this . map . get ( val )
26
+
27
+ // save
28
+ let prevNode = node . prev
29
+ // delete
30
+ prevNode . next = node . next
31
+ prevNode . next . prev = prevNode
32
+ this . map . delete ( val )
33
+ }
34
+ }
35
+
36
+ popleft ( ) {
37
+ let data = this . Left . next . val
38
+ this . Left . next = this . Left . next . next
39
+ this . Left . next . prev = this . Left
40
+ this . map . delete ( data )
41
+ return data
42
+ }
43
+
44
+ pushRight ( val ) {
45
+ let newNode = new ListNode ( val , this . Right )
46
+ newNode . prev = this . Right . prev
47
+ newNode . prev . next = newNode
48
+ this . Right . prev = newNode
49
+ this . map . set ( val , newNode )
50
+ }
51
+
52
+ update ( val ) {
53
+ this . pop ( val )
54
+ this . pushRight ( val )
55
+ }
56
+ }
57
+
58
+ /**
59
+ * @param {number } capacity
60
+ */
61
+ var LFUCache = function ( capacity ) {
62
+ this . capacity = capacity
63
+ this . valueMap = new Map ( )
64
+ this . countMap = new Map ( )
65
+ this . lftCount = 1
66
+ this . lists = [ ]
67
+ this . counter = ( key ) => {
68
+ let count = this . countMap . get ( key ) || 0
69
+ if ( this . lists [ count ] ) {
70
+ this . lists [ count ] . pop ( key )
71
+ }
72
+ if ( ! this . lists [ count + 1 ] ) {
73
+ this . lists [ count + 1 ] = new LinkedList ( )
74
+ }
75
+ this . lists [ count + 1 ] . pushRight ( key )
76
+ this . countMap . set ( key , count + 1 )
77
+ // console.log(this.lftCount == count, count, this.lists[count].len())
78
+ if ( this . lftCount == count && this . lists [ count ] && this . lists [ count ] . len ( ) === 0 ) {
79
+ this . lftCount ++
80
+ }
81
+ }
82
+ } ;
83
+
84
+ /**
85
+ * @param {number } key
86
+ * @return {number }
87
+ */
88
+ LFUCache . prototype . get = function ( key ) {
89
+ if ( ! this . valueMap . has ( key ) ) {
90
+ return - 1
91
+ }
92
+
93
+ this . counter ( key )
94
+ return this . valueMap . get ( key )
95
+ } ;
96
+
97
+ /**
98
+ * @param {number } key
99
+ * @param {number } value
100
+ * @return {void }
101
+ */
102
+ LFUCache . prototype . put = function ( key , value ) {
103
+
104
+ if ( ! this . valueMap . has ( key ) && this . valueMap . size == this . capacity ) {
105
+ // we need to evict
106
+ // console.log(this.lists[this.lftCount])
107
+ let evictedKey = this . lists [ this . lftCount ] . popleft ( )
108
+ this . valueMap . delete ( evictedKey )
109
+ this . countMap . delete ( evictedKey )
110
+ }
111
+
112
+ this . valueMap . set ( key , value )
113
+ this . counter ( key )
114
+ this . lftCount = Math . min ( this . countMap . get ( key ) , this . lftCount )
115
+ } ;
116
+ /**
117
+ * Your LFUCache object will be instantiated and called as such:
118
+ * var obj = new LFUCache(capacity)
119
+ * var param_1 = obj.get(key)
120
+ * obj.put(key,value)
121
+ */
0 commit comments