0405-2020-LEETCODE-LFU缓存-(哈希和双向链表)

需要注意的是:又要存操作数,又要存相同的操作数最古老的那一个,所以需要使用的是复合的数据结构。
代码来源:
https://leetcode-cn.com/problems/lfu-cache/solution/java-13ms-shuang-100-shuang-xiang-lian-biao-duo-ji/

package test0309;


import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

public class LFUCache1 {
    Map<Integer, Node> cache;
    Map<Integer, LinkedHashSet<Node>> freqMap;
    int size;
    int capacity;
    int min;

    public LFUCache1(int capacity){
        this.capacity = capacity;
        cache = new HashMap<>(capacity);
        freqMap = new HashMap<>();
    }
    public int get(int key){
        Node node = cache.get(key);
        if (node == null){
            return -1;
        }
        freqInc(node);//操作数 + 1,但是实际上是使原来操作数的set删掉这个node,
                      // 再把node的freq + 1,添加到(freq+1)的set中,最古老操作数当然会被在遍历时第一个删除。
        return node.value;
    }
    public void put(int key,int value){
        if (capacity == 0){
            return;
        }
        Node node = cache.get(key);
        if (node != null){
            //存在就更新
            node.value = value;
            freqInc(node);
        } else {
            if (size == capacity){
                //满了
                Node deadNode = removeNode();
                cache.remove(deadNode.key);
                size--;
            }
            //再添加
            Node newNode = new Node(key,value);
            cache.put(key,newNode);
            //往双向链表中添加新的节点
            addNode(newNode);
            size++;
        }
    }

    private void addNode(Node newNode) {
        LinkedHashSet<Node> set = freqMap.get(1);
        if (set == null){
            set = new LinkedHashSet<Node>();
            set.add(newNode);
            freqMap.put(1,set);
        }
        set.add(newNode);
        min = 1;
    }

    private Node removeNode() {
        LinkedHashSet<Node> set = freqMap.get(min);
        //最古老没有操作的那个
        Node deadNode = set.iterator().next();
        set.remove(deadNode);
        return deadNode;
    }

    private void freqInc(Node node) {
        //更新当前key对应的频次
        //因为当前节点的操作数已经改变,就需要把它从当前操作数的set中删除
        int freq = node.freq;
        LinkedHashSet<Node> set = freqMap.get(freq);
        set.remove(node);
        if (freq == min && set.size() == 0){
            min = 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);
    }


}



package test0309;

import java.util.HashMap;
import java.util.Map;

public class LFUCache2 {
    Map<Integer,Node> cache;
    Map<Integer,DoublyLinkedList> freqMap;
    int size;
    int capacity;
    int min;

    public LFUCache2(int capacity){
        this.capacity = capacity;
        cache = new HashMap<>(capacity);
        freqMap = new HashMap<>();
    }
    public int get(int key){
        Node node = cache.get(key);
        if (node == null){
            return -1;
        }
        freqInc(node);
        return node.value;
    }
    public void put(int key,int value){
        if (capacity == 0){
            return;
        }

        Node node = cache.get(key);
        if (node != null){
            //有这个key,就更新
            node.value = value;
            //操作数加1
            freqInc(node);
        } else {
            if (size == capacity){
                DoublyLinkedList minList = freqMap.get(min);
                cache.remove(minList.tail.pre.key);
                minList.removeNode(minList.tail.pre);
                size--;
            }
            Node newNode = new Node(key,value);
            cache.put(key,newNode);
            DoublyLinkedList list = freqMap.get(1);
            if (list == null){
                list = new DoublyLinkedList();
                freqMap.put(1,list);

            }
            list.addNode(newNode);
            size++;
            min = 1;
        }

    }




    private void freqInc(Node node) {
        //从对应的列表中移除
        int freq = node.freq;
        DoublyLinkedList list = freqMap.get(freq);
        list.removeNode(node);
        if (freq == min && list.head.post == list.tail){
            min = freq + 1;
        }
        node.freq++;
        DoublyLinkedList newList = freqMap.get(freq + 1);
        if (newList == null){
            newList = new DoublyLinkedList();
            freqMap.put(freq + 1,newList);
        }
        newList.addNode(node);
    }

    public static void main(String[] args) {
        LFUCache2 cache2 = new LFUCache2(2);
        cache2.put(1,1);
    }

}


你可能感兴趣的:(LEETCODE)