type biNode struct { key int val int cnt int prev *biNode next *biNode } type biList struct { head *biNode tail *biNode } func newBiList() *biList { head, tail := &biNode{}, &biNode{} head.next = tail tail.prev = head li := &biList{head, tail} return li } func (li *biList) remove(node *biNode) { node.prev.next = node.next node.next.prev = node.prev } type LFUCache struct { capacity int size int min int cache map[int]*biNode freq map[int]*biList } func Constructor(capacity int) LFUCache { var lfu LFUCache lfu.capacity = capacity lfu.cache = make(map[int]*biNode) lfu.freq = make(map[int]*biList) return lfu } func (this *LFUCache) Get(key int) int { if node, ok := this.cache[key]; ok { this.touch(node) return node.val } return -1 } func (this *LFUCache) Put(key int, value int) { if this.capacity == 0 { return } // Can not put new node. if node, ok := this.cache[key]; ok { this.touch(node) node.val = value return } // If the key already exists, touch it and update the value. if this.size == this.capacity { li := this.freq[this.min] delete(this.cache, li.tail.prev.key) li.remove(li.tail.prev) if li.head.next == li.tail { delete(this.freq, this.min) } this.size-- } // If the cache is full, remove the last element in the least freq list. newNode := &biNode{key, value, 1, nil, nil} this.insert(newNode) this.cache[key] = newNode this.min = 1 this.size++ // Then, insert new node. } func (this *LFUCache) insert(node *biNode) { li := this.freq[node.cnt] if li == nil { li = newBiList() this.freq[node.cnt] = li } node.next = li.head.next node.prev = li.head li.head.next = node node.next.prev = node } func (this *LFUCache) touch(node *biNode) { li := this.freq[node.cnt] li.remove(node) if li.head.next == li.tail { delete(this.freq, node.cnt) if node.cnt == this.min { this.min++ } } node.cnt++ this.insert(node) } /** * Your LFUCache object will be instantiated and called as such: * obj := Constructor(capacity); * param_1 := obj.Get(key); * obj.Put(key,value); */