题解 | #设计LFU缓存结构#
设计LFU缓存结构
https://www.nowcoder.com/practice/93aacb4a887b46d897b00823f30bfea1
package main
import (
"container/heap"
"time"
)
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* lfu design
* @param operators int整型二维数组 ops
* @param k int整型 the k
* @return int整型一维数组
*/
func LFU(operators [][]int, k int) []int {
cache := Constructor(k)
var result []int
for _, op := range operators {
switch op[0] {
case 1: // set操作
cache.Set(op[1], op[2])
case 2: // get操作
result = append(result, cache.Get(op[1]))
}
}
return result
}
// lfuCacheItem 表示缓存中的一个条目
type lfuCacheItem struct {
key int
value int
frequency int
timestamp time.Time
index int // 堆中的索引
}
// lfuHeap 实现了一个最小堆
type lfuHeap []*lfuCacheItem
func (h lfuHeap) Len() int { return len(h) }
func (h lfuHeap) Less(i, j int) bool { // 优先比较频率,然后比较时间戳
return h[i].frequency < h[j].frequency || (h[i].frequency == h[j].frequency && h[i].timestamp.Before(h[j].timestamp))
}
func (h lfuHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
h[i].index = i
h[j].index = j
}
func (h *lfuHeap) Push(x interface{}) {
n := len(*h)
item := x.(*lfuCacheItem)
item.index = n
*h = append(*h, item)
}
func (h *lfuHeap) Pop() interface{} {
old := *h
n := len(old)
item := old[n-1]
item.index = -1 // for safety
*h = old[0 : n-1]
return item
}
// LFUCache 是LFU缓存的主结构
type LFUCache struct {
capacity int
items map[int]*lfuCacheItem
heap lfuHeap
}
// Constructor 创建一个新的LFU缓存
func Constructor(capacity int) LFUCache {
return LFUCache{
capacity: capacity,
items: make(map[int]*lfuCacheItem),
heap: make(lfuHeap, 0, capacity),
}
}
// Get 从缓存中获取一个值
func (cache *LFUCache) Get(key int) int {
if item, exists := cache.items[key]; exists {
item.frequency++
item.timestamp = time.Now()
heap.Fix(&cache.heap, item.index)
return item.value
}
return -1
}
// Set 向缓存中插入一个值
func (cache *LFUCache) Set(key int, value int) {
if cache.capacity == 0 {
return
}
if item, exists := cache.items[key]; exists {
item.value = value
item.frequency++
item.timestamp = time.Now()
heap.Fix(&cache.heap, item.index)
return
}
if len(cache.items) == cache.capacity {
// 移除使用频率最低且时间戳最早的条目
removed := heap.Pop(&cache.heap).(*lfuCacheItem)
delete(cache.items, removed.key)
}
// 添加新条目
newItem := &lfuCacheItem{
key: key,
value: value,
frequency: 1,
timestamp: time.Now(),
}
cache.items[key] = newItem
heap.Push(&cache.heap, newItem)
}
