[Práctica diaria] - Por lo menos frecuente (el LFU) estructura de datos de caché

título Descripción

Diseñar e implementar la estructura de datos (LFU) caché utilizada con menos frecuencia. Debe apoyar las siguientes operaciones: obtener y poner.
get (clave) - Si existe la clave en la memoria caché, a continuación, obtener el valor de la clave (siempre positivo), en otro caso -1.
poner (clave, valor) - si la clave no existe, o inserto valor establecido. Cuando la caché alcanza su capacidad, debe estar en antes de insertar un nuevo proyecto, el proyecto no es el más frecuentemente utilizado es válido. En este problema, cuando hay un empate (es decir, dos o más teclas que tienen la misma frecuencia), se retira la llave menos utilizado recientemente.
El título proviene del leetcode, haga clic para entrar

Leer título

Ejemplo:

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

Estructuradas del siguiente modo:
Aquí Insertar imagen Descripción

código

clase 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);
        }
    }


}

nodo entregable

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

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

    public Node() {

    }
}

prueba

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


    }
}
  • El resultado:
    Aquí Insertar imagen Descripción
Publicado 32 artículos originales · ganado elogios 7 · vistas 4075

Supongo que te gusta

Origin blog.csdn.net/weixin_45676630/article/details/105326871
Recomendado
Clasificación