[LeetCode] LFU Cache

来源:互联网 发布:tf卡测速软件 编辑:程序博客网 时间:2024/05/29 16:32

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.

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

Example:

LFUCache cache = new LFUCache( 2 /* capacity */ );cache.put(1, 1);cache.put(2, 2);cache.get(1);       // returns 1cache.put(3, 3);    // evicts key 2cache.get(2);       // returns -1 (not found)cache.get(3);       // returns 3.cache.put(4, 4);    // evicts key 1.cache.get(1);       // returns -1 (not found)cache.get(3);       // returns 3cache.get(4);       // returns 4

public class LFUCache {    TDLinkedList tdList;HashMap<Integer,Node> map;int capacity;    public LFUCache(int capacity) {    tdList=new TDLinkedList();        map=new HashMap<Integer,Node>();        this.capacity=capacity;    }        public int get(int key) {        if(map.get(key)==null) return -1;        else{        Node node=map.get(key);        tdList.addOneTime(node);        return node.value;        }    }        public void put(int key, int value) {    if(capacity==0) return;        if(map.containsKey(key)){        map.get(key).value=value;        tdList.addOneTime(map.get(key));        }else{        if(map.size()==capacity){        map.remove(key);        int keyTemp=tdList.removeFirst();        map.remove(keyTemp);        }        Node temp=new Node(key,value,1);        map.put(key,temp);        tdList.add(temp);        }    }        class TDLinkedList{    Node head;    Node tail;    public TDLinkedList() {head=new Node(-1,-1,Integer.MIN_VALUE);tail=new Node(-1,-1,Integer.MAX_VALUE);head.next=tail;tail.pre=head;}    public Node add(Node node){    addNodeAfterAndDown(head,node);    return node;    }       private Node addNodeAfterAndDown(Node head,Node node){    if(head.next.times!=node.times){    Node top=new Node(-1,-1,node.times);    top.pre=head;top.next=head.next;    head.next.pre=top;head.next=top;    }    Node temp=head.next;    while(temp.down!=null) temp=temp.down;    temp.down=node;node.up=temp;    return node;    }    public int removeFirst(){    if(head.next==tail) return -1;    Node temp=head.next;    Node down=temp.down;    temp.down=down.down;    if(down.down!=null) down.down.up=temp;    return down.key;    }    public Node addOneTime(Node node){    node.times++;    Node top=node;    while(top.up!=null){    top=top.up;    }    node.up.down=node.down;    if(node.down!=null) node.down.up=node.up;    if(top.down==null){    top.next.pre=top.pre;    top.pre.next=top.next;    top=top.pre;    }    node.up=null;node.down=null;    addNodeAfterAndDown(top,node);    return node;    }    }    class Node{    int key,value,times;    Node pre,next,up,down;public Node(int key, int value,int times) {this.key = key;this.value = value;this.times=times;}    }}/** * 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); */