题解 | #设计LFU缓存结构#
设计LFU缓存结构
https://www.nowcoder.com/practice/93aacb4a887b46d897b00823f30bfea1
import java.util.*; public class Solution { public int[] LFU(int[][] operators, int k) {//批量操作 LFUCache lfucache = new LFUCache(k); List<Integer> list = new ArrayList<>(); for (int[] operator : operators) { if (operator[0] == 1) {//1-新增 lfucache.set(operator[1], operator[2]); } else if (operator[0] == 2) {//2-获取 int value = lfucache.get(operator[1]); list.add(value); } } int[] res = new int[list.size()]; for (int i = 0; i < res.length; i++) { res[i] = list.get(i); } return res; } } //LFU缓存设置 class LFUCache { class Node { int key; int value; int freq;//频率 public Node(int key, int value, int freq) { this.key = key; this.value = value; this.freq = freq; } } private int capacity; private int size; private int minFreq;//频率最低 private HashMap<Integer, Node> cache;//缓存 private HashMap<Integer, LinkedHashSet<Node>> freqList;//缓存频率表(每个频次都有一个表),因为有很多相同频次的数据 public LFUCache(int capacity) { this.capacity = capacity; size = 0; minFreq = 0; cache = new HashMap<>(); freqList = new HashMap<>(); } public int get(int key) {//获取 if (!cache.containsKey(key)) { return -1; } Node node = cache.get(key); updateNode(node); return node.value; } public void set(int key, int value) { if (capacity == 0) { return; } //存在则更新 if (cache.containsKey(key)) { Node node = cache.get(key); node.value = value; updateNode(node); } else {//不存在则新增 if (size == capacity) {//空间占满,删除频率最低数据 LinkedHashSet<Node> minFreqList = freqList.get( minFreq);//获取最小频率列表 Node node = minFreqList.iterator().next();//获取第一个节点 minFreqList.remove(node);//移除节点 cache.remove(node.key);//缓存也移除 size--; } //新增节点-加入缓存-加入频率表-更新最小频次和缓存大小 Node newNode = new Node(key, value, 1); cache.put(key, newNode); LinkedHashSet<Node> newList = freqList.getOrDefault(1, new LinkedHashSet<>()); newList.add(newNode); freqList.put(1, newList); minFreq = 1; size++; } } private void updateNode(Node node) {//更新数据频率 //取出-移除 LinkedHashSet<Node> oldList = freqList.get(node.freq);//获取该频次的列表 oldList.remove(node);//移除该节点 if (oldList.isEmpty() && node.freq == minFreq) {//如果这数据是该表最后一个数据并且是最低频率 //更新最小频率 minFreq++; } //更新-新增 node.freq++; //获取该频次的列表(没有则新增) LinkedHashSet<Node> newList = freqList.getOrDefault(node.freq, new LinkedHashSet<>()); newList.add(node);//列表新增节点 freqList.put(node.freq, newList);//放入(列表存在则更新,不存在则新增) } }