Files
LeetCode-Go/template/LFUCache.go
2021-01-03 23:48:14 +08:00

197 lines
4.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package template
import "container/list"
// LFUCache define
type LFUCache struct {
nodes map[int]*list.Element
lists map[int]*list.List
capacity int
min int
}
type node struct {
key int
value int
frequency int
}
// Constructor define
func Constructor(capacity int) LFUCache {
return LFUCache{nodes: make(map[int]*list.Element),
lists: make(map[int]*list.List),
capacity: capacity,
min: 0,
}
}
// Get define
func (lfuCache *LFUCache) Get(key int) int {
value, ok := lfuCache.nodes[key]
if !ok {
return -1
}
currentNode := value.Value.(*node)
lfuCache.lists[currentNode.frequency].Remove(value)
currentNode.frequency++
if _, ok := lfuCache.lists[currentNode.frequency]; !ok {
lfuCache.lists[currentNode.frequency] = list.New()
}
newList := lfuCache.lists[currentNode.frequency]
newNode := newList.PushFront(currentNode)
lfuCache.nodes[key] = newNode
if currentNode.frequency-1 == lfuCache.min && lfuCache.lists[currentNode.frequency-1].Len() == 0 {
lfuCache.min++
}
return currentNode.value
}
// Put define
func (lfuCache *LFUCache) Put(key int, value int) {
if lfuCache.capacity == 0 {
return
}
if currentValue, ok := lfuCache.nodes[key]; ok {
currentNode := currentValue.Value.(*node)
currentNode.value = value
lfuCache.Get(key)
return
}
if lfuCache.capacity == len(lfuCache.nodes) {
currentList := lfuCache.lists[lfuCache.min]
backNode := currentList.Back()
delete(lfuCache.nodes, backNode.Value.(*node).key)
currentList.Remove(backNode)
}
lfuCache.min = 1
currentNode := &node{
key: key,
value: value,
frequency: 1,
}
if _, ok := lfuCache.lists[1]; !ok {
lfuCache.lists[1] = list.New()
}
newList := lfuCache.lists[1]
newNode := newList.PushFront(currentNode)
lfuCache.nodes[key] = newNode
}
/**
* Your LFUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/
// Index Priority Queue
// import "container/heap"
// type LFUCache struct {
// capacity int
// pq PriorityQueue
// hash map[int]*Item
// counter int
// }
// func Constructor(capacity int) LFUCache {
// lfu := LFUCache{
// pq: PriorityQueue{},
// hash: make(map[int]*Item, capacity),
// capacity: capacity,
// }
// return lfu
// }
// func (this *LFUCache) Get(key int) int {
// if this.capacity == 0 {
// return -1
// }
// if item, ok := this.hash[key]; ok {
// this.counter++
// this.pq.update(item, item.value, item.frequency+1, this.counter)
// return item.value
// }
// return -1
// }
// func (this *LFUCache) Put(key int, value int) {
// if this.capacity == 0 {
// return
// }
// // fmt.Printf("Put %d\n", key)
// this.counter++
// // 如果存在,增加 frequency再调整堆
// if item, ok := this.hash[key]; ok {
// this.pq.update(item, value, item.frequency+1, this.counter)
// return
// }
// // 如果不存在且缓存满了,需要删除。在 hashmap 和 pq 中删除。
// if len(this.pq) == this.capacity {
// item := heap.Pop(&this.pq).(*Item)
// delete(this.hash, item.key)
// }
// // 新建结点,在 hashmap 和 pq 中添加。
// item := &Item{
// value: value,
// key: key,
// count: this.counter,
// }
// heap.Push(&this.pq, item)
// this.hash[key] = item
// }
// // An Item is something we manage in a priority queue.
// type Item struct {
// value int // The value of the item; arbitrary.
// key int
// frequency int // The priority of the item in the queue.
// count int // use for evicting the oldest element
// // The index is needed by update and is maintained by the heap.Interface methods.
// index int // The index of the item in the heap.
// }
// // A PriorityQueue implements heap.Interface and holds Items.
// type PriorityQueue []*Item
// func (pq PriorityQueue) Len() int { return len(pq) }
// func (pq PriorityQueue) Less(i, j int) bool {
// // We want Pop to give us the highest, not lowest, priority so we use greater than here.
// if pq[i].frequency == pq[j].frequency {
// return pq[i].count < pq[j].count
// }
// return pq[i].frequency < pq[j].frequency
// }
// func (pq PriorityQueue) Swap(i, j int) {
// pq[i], pq[j] = pq[j], pq[i]
// pq[i].index = i
// pq[j].index = j
// }
// func (pq *PriorityQueue) Push(x interface{}) {
// n := len(*pq)
// item := x.(*Item)
// item.index = n
// *pq = append(*pq, item)
// }
// func (pq *PriorityQueue) Pop() interface{} {
// old := *pq
// n := len(old)
// item := old[n-1]
// old[n-1] = nil // avoid memory leak
// item.index = -1 // for safety
// *pq = old[0 : n-1]
// return item
// }
// // update modifies the priority and value of an Item in the queue.
// func (pq *PriorityQueue) update(item *Item, value int, frequency int, count int) {
// item.value = value
// item.count = count
// item.frequency = frequency
// heap.Fix(pq, item.index)
// }