LFU Cache

Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted.

Note that the number of times an item is used is the number of calls to the get and put functions for that item since it was inserted. This number is set to zero when the item is removed.

Follow up:
Could you do both operations in O(1) time complexity?

思路: 这题是LRU的升级版,这里仍然需要一个hashmap<Key, Node>  用来用key来找node,比LRU多的部分就是需要一个frequency map,同时 key 是fre,value是个list,这个list跟LRU的list一模一样,只不过是每一个fre都有这么一个list,所以需要写一个DList的类,来加node,减node,remove last node。Time: O(1), Space: O(N)

Fre, DList<> 这个DList就是每个频率所维护的Least Recent used list;

class LFUCache {
    
    public class Node {
        public int key;
        public int value;
        public int fre;
        public Node next;
        public Node pre;
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
            this.next = null;
            this.pre = null;
            this.fre = 1;
        }
    }
    
    public class DList {
        public int size;
        public Node head;
        public Node tail;
        
        public DList() {
            this.size = 0;
            this.head = new Node(-1, -1);
            this.tail = new Node(-1, -1);
            head.next = tail;
            tail.pre = head;
        }
        
        // moveToHead;
        public void addNode(Node node) { 
            Node headnext = head.next;
            head.next = node;
            node.next = headnext;
            headnext.pre = node;
            node.pre = head;
            this.size++;
        }
        
        public Node DeleteLastNode() {
            if(size == 0) {
                return null;
            }
            Node last = tail.pre;
            last.pre.next = tail;
            tail.pre = last.pre;
            this.size--;
            return last;
        }
        
        public void removeNode(Node node) {
            node.pre.next = node.next;
            node.next.pre = node.pre;
            this.size--;
        }
    }

    public int capacity;
    public int minfre;
    //             key,     node
    public HashMap<Integer, Node> hashmap;
    //              fre,    LR DList
    public HashMap<Integer, DList> fremap;
    
    
    public LFUCache(int capacity) {
        this.capacity = capacity;
        this.hashmap = new HashMap<>();
        this.fremap = new HashMap<>();
    }
    
    public int get(int key) {
        if(!hashmap.containsKey(key)) {
            return -1;
        } else {
            // contains the key;
            Node node = hashmap.get(key);
            updateFreMap(node);
            return node.value;
        }
    }
    
    public void updateFreMap(Node node) {
            int fre = node.fre;
            DList dlist = fremap.get(fre);
            dlist.removeNode(node);
            if(dlist.size == 0) {
                fremap.remove(fre);
                if(fre == minfre) {
                    minfre++;
                }
            }
            // add to new fre DList;
            node.fre++;
            fremap.putIfAbsent(node.fre, new DList());
            fremap.get(node.fre).addNode(node);
    }
    
    public void put(int key, int value) {
        if(this.capacity == 0) {
            return;
        }
        if(hashmap.containsKey(key)) {
            Node node = hashmap.get(key);
            node.value = value;
            updateFreMap(node);
        } else {
            // not contains;
            if(hashmap.keySet().size() < this.capacity) {
                Node node = new Node(key, value);
                minfre = 1;
                fremap.putIfAbsent(minfre, new DList());
                fremap.get(minfre).addNode(node);
                hashmap.put(key, node);
            } else {
                // evict last node;
                DList dlist = fremap.get(minfre);
                Node lastnode = dlist.DeleteLastNode();
                hashmap.remove(lastnode.key);
                
                // add new node;
                minfre = 1;
                Node node = new Node(key, value);
                fremap.putIfAbsent(minfre, new DList());
                fremap.get(minfre).addNode(node);
                hashmap.put(key, node);
            }
        }
    } 
}

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache obj = new LFUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值