[Pratique quotidienne] - moins fréquemment utilisé la structure de données de cache (LFU)

Titre description

Concevoir et mettre en œuvre la moins fréquemment utilisée structure de données de cache (LFU). Il devrait soutenir les opérations suivantes: obtenir et mettre.
get (clé) - si la clé existe dans le cache, puis obtenir la valeur (toujours positive) clé, sinon -1.
mettre (clé, valeur) - si la clé n'existe pas, ou insérer la valeur définie. Lorsque le cache atteint sa capacité, il devrait être en avant d' insérer un nouveau projet, le projet est le plus fréquemment utilisé est invalide. Dans ce problème, quand il y a un lien ( à savoir, deux ou plusieurs touches ayant la même fréquence), la clé moins récemment utilisée est retirée.
Le titre provient de l'leetcode, cliquez pour entrer

Lire le titre

exemple:

LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回 1
cache.put(3, 3);    // 去除 key 2
cache.get(2);       // 返回 -1 (未找到key 2)
cache.get(3);       // 返回 3
cache.put(4, 4);    // 去除 key 1
cache.get(1);       // 返回 -1 (未找到 key 1)
cache.get(3);       // 返回 3
cache.get(4);       // 返回 4

Conçu comme suit:
Insérer ici l'image Description

code

classe LFUCache

public class LFUCache {
    private int cap; // 缓存总容量
    private int size; // 当前缓存使用量
    private HashMap<Integer, Node> cache; // 缓存Map
    private HashMap<Integer, ArrayList<Node>> freqNodes; // 记录使用次数

    // 打印当前缓存内容 测试用
    public void printCache(){
        for (Map.Entry<Integer, Node> entry : cache.entrySet()){
            System.out.print(entry.getKey()+" ");
        }
        System.out.println();
    }
    public LFUCache(int capacity) {
        this.cap = capacity;
        this.cache = new HashMap<Integer, Node>(capacity);
        this.freqNodes = new HashMap<Integer, ArrayList<Node>>();
    }

    public int get(int key) {
        Node node = cache.get(key);
        if (node == null) {
            return -1;
        }
        node.freq++;
        // 次数有变化,需要更新记录使用次数的Map
        adjustPosition(node);
        return node.value;
    }

    private void adjustPosition(Node node) {
        if (freqNodes.containsKey(node.freq - 1)) {
            freqNodes.get(node.freq - 1).remove(node);
            // list为空时需要将它从记录使用次数的map中移除
            if (freqNodes.get(node.freq - 1).size() == 0) {
                freqNodes.remove(node.freq - 1);
            }
        }
        // 将node加到新的list,如果不存在需要新建
        if (freqNodes.containsKey(node.freq)) {
            freqNodes.get(node.freq).add(node);
        } else {
            ArrayList<Node> newNodes = new ArrayList<Node>();
            newNodes.add(node);
            freqNodes.put(node.freq, newNodes);
        }

    }


    public int getMinReq() {
        int req  = 0;
        boolean flag = true;
        // 循环获取最小key,没有什么好说的
        for (Map.Entry<Integer, ArrayList<Node>> entry : freqNodes.entrySet()) {
            if(flag){
                req = entry.getKey();
                flag = false;
            }else{
                req = Integer.min(req, entry.getKey());
            }
        }
        return rep;
    }

    public void put(int key, int value) {
        // 容量为0无法存储
        if (cap == 0) return;
        // 判断是否已经存在
        Node node = cache.get(key);

        if (node == null) {
            // 不存在的情况,需要判断缓存是否已满,没有满,直接加入,若满了,需要找到使用次数最少最近调用时间最靠后的
            if (size == cap) {
            	// 找到使用次数最少且最近一次使用时间最长的元素
                int remove = getMinReq();
                int k = freqNodes.get(remove).get(0).key;
                // 将找到的元素从原来的list中删除
                freqNodes.get(remove).remove(0);
                // 从缓存中删除
                cache.remove(k);
                node = new Node(key,value);
                // 新增时,需要更新记录使用次数的Map
                adjustPosition(node);
                cache.put(key, node);
            } else {
                Node newNode = new Node(key, value);
                // 新增时,需要更新记录使用次数的Map
                adjustPosition(newNode);// 加入缓存
                cache.put(key, newNode);
                // 当前缓存大小增加
                size++;
            }

        } else {
            // 已存在的情况,更新调用次数,更新值
            node.value = value;
            node.freq++;
            // 次数有变化,需要更新记录使用次数的Map
            adjustPosition(node);
        }
    }


}

Deliverable noeud

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

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

    public Node() {

    }
}

test

public class Test {
    public static void main(String[] args) {
        LFUCache lfuCache = new LFUCache(5);
        lfuCache.put(1,1);
        lfuCache.put(2,2);
        lfuCache.put(3,3);
        lfuCache.put(4,4);
        lfuCache.put(5,5);
        System.out.println(lfuCache.get(1));
        System.out.println(lfuCache.get(2));
        System.out.println(lfuCache.get(4));
        System.out.println(lfuCache.get(5));
        lfuCache.put(6,6);
        System.out.println("push(6,6)此时cache:");
        lfuCache.printCache();
        System.out.println(lfuCache.get(3));
        System.out.println(lfuCache.get(6));
        System.out.println("================此时剩余12456 均只调用一次 1距离上次调用时间最久================");
        lfuCache.put(7,7); // 此时应该为 24567
        System.out.println("push(7,7),此时cache:");
        lfuCache.printCache();
        System.out.println(lfuCache.get(1));// 应为 -1


    }
}
  • Le résultat:
    Insérer ici l'image Description
Publié 32 articles originaux · a gagné les éloges 7 · vues 4075

Je suppose que tu aimes

Origine blog.csdn.net/weixin_45676630/article/details/105326871
conseillé
Classement