数据结构题:LFU缓存

一、题目

请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。它应该支持以下操作:get 和 put。

get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。

put(key, value) - 如果键已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近 最少使用的键。

「项的使用次数」就是自插入该项以来对其调用 get 和 put 函数的次数之和。使用次数会在对应项被移除后置为 0 。

二、思路

1)封装一个包含数据内容以及访问频次的节点。

2) 通过双向链表记录每个访问频次对应的节点。

3)根据添加和删除节点更新记录缓存中节点的最小访问频次。

三、实现

public class LFUCache {
    Map<Integer, Node> cache;
    Map<Integer, LinkedHashSet<Node>> freqMap;
    int minFreq;
    int capacity;

    public LFUCache(int capacity) {
        cache = new HashMap<>(capacity);
        freqMap = new HashMap<>();
        minFreq = 1;
        this.capacity = capacity;
    }

    public int get(int key) {
        Node node = cache.get(key);

        if (node == null) {
            return -1;
        }

        updateFreq(node);

        return node.value;
    }

    public void put(int key, int value) {
        if (capacity == 0) {
            return;
        }
        Node node = cache.get(key);

        if (node == null) {
            if (cache.size() == capacity) {
                removeNode();
            }
            Node newNode = new Node(key, value);
            addNode(newNode);
        } else {
            node.value = value;
            updateFreq(node);
        }
    }

    public void updateFreq(Node node) {
        int freq = node.freq;
        LinkedHashSet<Node> set = freqMap.get(freq);
        set.remove(node);
        if (freq == minFreq && set.size() == 0) {
            minFreq = freq + 1;
        }

        node.freq++;
        LinkedHashSet<Node> newSet = freqMap.get(freq + 1);
        if (newSet == null) {
            newSet = new LinkedHashSet<>();
            freqMap.put(freq + 1, newSet);
        }
        newSet.add(node);
    }

    public void removeNode() {
        LinkedHashSet<Node> set = freqMap.get(minFreq);
        Node node = set.iterator().next();
        set.remove(node);
        cache.remove(node.key);
    }

    public void addNode(Node node) {
        int freq = node.freq;
        LinkedHashSet<Node> set = freqMap.get(freq);
        if (set == null) {
            set = new LinkedHashSet<>();
            freqMap.put(node.freq, set);
        }
        set.add(node);
        minFreq = node.freq;
        cache.put(node.key, node);
    }

    class Node {
        int key;
        int value;
        int freq;

        public Node(int key, int value) {
            this.key = key;
            this.value = value;
            freq = 1;
        }
    }

}
发布了83 篇原创文章 · 获赞 0 · 访问量 4500

猜你喜欢

转载自blog.csdn.net/zhangdx001/article/details/105542730
今日推荐