题解 | #设计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);//放入(列表存在则更新,不存在则新增)
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务