LRU Cache | Practice | GeeksforGeeks

Design a data structure that works like a LRU Cache. Here cap denotes the capacity of the cache and Q denotes the number of queries. Query can be of two types:

SET x y : sets the value of the key x with value y 
GET x : gets the key of x if present else returns -1.

SET x y : sets the value of the key x with value y 
GET x : gets the key of x if present else returns -1.

The LRUCache class has two methods get() and set() which are defined as follows.

get(key)   : returns the value of the key if it already exists in the cache otherwise returns -1.
set(key, value) : if the key is already present, update its value. If not present, add the key-value pair to the cache. If the cache reaches its capacity it should invalidate the least recently used item before inserting the new item.
In the constructor of the class the capacity of the cache should be intitialized.

get(key)   : returns the value of the key if it already exists in the cache otherwise returns -1.
set(key, value) : if the key is already present, update its value. If not present, add the key-value pair to the cache. If the cache reaches its capacity it should invalidate the least recently used item before inserting the new item.
In the constructor of the class the capacity of the cache should be intitialized.
 
Example 1:
Input:
cap = 2
Q = 2
Queries = SET 1 2 GET 1
Output: 2
Explanation: 
Cache Size = 2

SET 1 2 GET 1
SET 1 2 : 1 -> 2

GET 1 : Print the value corresponding
to Key 1, ie 2.


Example 2:
Input:
cap = 2
Q = 8
Queries = SET 1 2 SET 2 3 SET 1 5
SET 4 5 SET 6 7 GET 4 SET 1 2 GET 3
Output: 5 -1
Explanation: 
Cache Size = 2
SET 1 2 : 1 -> 2

SET 2 3 : 1 -> 2, 2 -> 3 (the most recently 
used one is kept at the rightmost position) 

SET 1 5 : 2 -> 3, 1 -> 5

SET 4 5 : 1 -> 5, 4 -> 5 (Cache size is 2, hence 
we delete the least recently used key-value pair)

SET 6 7 : 4 -> 5, 6 -> 7 

GET 4 : Prints 5 (The cache now looks like
6 -> 7, 4->5)

SET 1 2 : 4 -> 5, 1 -> 2 
(Cache size is 2, hence we delete the least 
recently used key-value pair)

GET 3 : No key value pair having 
key = 3. Hence, -1 is printed.


Your Task:
You don't need to read input or print anything . Complete the constructor and get(), set() methods of the class LRUcache. 

Expected Time Complexity: O(1) for both get() and set().
Expected Auxiliary Space: O(1) for both get() and set(). 
(Although, you may use extra space for cache storage and implementation purposes).

Constraints:
1 <= cap <= 1000
1 <= Q <= 100000
1 <= x, y <= 1000
0
bhardwajji2 days ago
easy c++ using 2 map and list
 
unordered_map<int,int>m;
    unordered_map<int,list<int>::iterator>pata;
    list<int>l;
    int currsize;  // overall capacity
    int size;
    
    LRUCache(int cap)
    {
        currsize = cap;
        size=0;
    }
    
    int get(int key)
    {
        if(m.find(key)==m.end())
            return -1;
        list<int>::iterator add = pata[key];
        l.erase(add);
        l.push_front(key);
        pata[key] = l.begin();
        
        return m[key];
    }
    
    void set(int key, int value)
    {
        if(m.find(key)!=m.end()){
            m[key] = value;
            list<int>::iterator add = pata[key];
            l.erase(add);
            l.push_front(key);
            pata[key]=l.begin();
        }
        else{
            m[key]=value;
            l.push_front(key);
            pata[key]=l.begin();
            size++;
        
            if(size>currsize){
                int k=l.back();
                l.pop_back();
                m.erase(k);
                pata.erase(k);
            }
        }
    }
0
aman hamid5 days ago
Solution using two maps:
One map for storing the current elements
Second map for keeping track of least recently used element
 
class LRUCache{private:
   public:   //Constructor for initializing the cache capacity with the given value.   int size = 0;   int c = 0;   int priority = 0;   int lp = 0;   unordered_map<int,pair<int,int>> m;   unordered_map<int,int> p;   LRUCache(int cap)   {       // code here       c = cap;   }      //Function to return value corresponding to the key.   int get(int key)   {       // your code here       auto it = m.find(key);       if(it==m.end()) {           return -1;       }       pair<int,int> vp = {(it->second).first,priority};       auto itr = p.find((it->second).second);       if(itr!=p.end()) {           p.erase(itr->first);       }       m[key] = vp;       p[priority] = key;       priority++;       return (it->second).first;   }      //Function for storing key-value pair.   void set(int key, int value)   {       // your code here          pair<int,int> vp;       auto it = m.find(key);       if(it!=m.end()) {           int r = (it->second).second;           p.erase(r);           vp = {value,priority};           m[key] = vp;           p[priority] = key;           priority = priority+1;       } else {           if(size==c) {               while(p.find(lp)==p.end()) {                   lp++;               }               int rem = p[lp];               p.erase(lp);               m.erase(rem);               vp = {value,priority};               m[key] = vp;               p[priority] = key;               priority++;           } else {               vp = {value,priority};               m[key] = vp;               p[priority] = key;               priority = priority+1;               size++;           }       }   }};
0
danish_nitdgp5 days ago
Easy and simple C++ solution.
O(1) Time for Both Get and set.
Using dounly Linked List and HashMap.
 
class LRUCache {
public:
    class node {
        public:
            int key;
            int val;
            node* next;
            node* prev;
            node(int newkey, int newval){
                key = newkey;
                val = newval;
            }
        };
    
    node* head = new node(-1,-1);
    node* tail = new node(-1,-1);
    int cap;
    unordered_map<int,node*> m;
    
    LRUCache(int capacity) {
        cap = capacity;
        head->next = tail;
        tail->prev = head;        
    }
    
    void addnode(node* newnode){
        node *temp = head->next;
        newnode->next = temp;
        newnode->prev = head;
        head->next = newnode;
        temp->prev = newnode;
    }
    
    void deletenode(node* delnode){
        node *delprev = delnode->prev;
        node *delnext = delnode->next;
        delnext->prev = delprev;
        delprev->next = delnext;        
    }
    
    int get(int key) {
        if(m.find(key)!=m.end()){
            node *resnode = m[key];
            int res = resnode->val;
            m.erase(key);
            deletenode(resnode);
            addnode(resnode);
            m[key] = head->next;
            return res;
        } else return -1;
        
    }
    
    void set(int key, int value) {
        if(m.find(key)!=m.end()){
            node *existingnode = m[key];
            m.erase(key);
            deletenode(existingnode);
        }
        if(m.size()==cap){
            m.erase(tail->prev->key);
            deletenode(tail->prev);
        }        
        addnode(new node(key,value));
        m[key] = head->next;
    }
};
 
 
0
roadslestraveled2 weeks ago
I get a wrong answer when using static variables but on removing static keyword my solution passes. Can someone pls explain this why is it happening???
class LRUCache
{
   //Constructor for initializing the cache capacity with the given value.
   
   static Node head = new Node(0,0);
   static Node tail = new Node(0,0);
   static HashMap<Integer,Node> map = new HashMap<>();
   static int capacity=0 ;
   LRUCache(int cap)
   {
       //code here
       this.capacity = cap;
       head.next = tail;
       tail.prev = head;
       
       
   }
   //Function to return value corresponding to the key.
   public  static int get(int key)
   {
       // your code here
       if(map.get(key) != null){
           Node node = map.get(key);
           remove(node);
           insert(node);
           return node.val;
       }
       else{
           return -1;
       }
       
   }
   //Function for storing key-value pair.
   public static void set(int key, int value)
   {
       // your code here
        if(map.get(key) != null){
           remove(map.get(key));
       }
       if(map.size() == capacity){
           remove(tail.prev);
       }
       insert(new Node(key,value));
   }
   private static void remove(Node node){
       map.remove(node.key);
       node.prev.next = node.next;
       node.next.prev = node.prev;
   }
   
   private  static void insert(Node node){
       
       map.put(node.key,node);
       node.next = head.next;
       node.next.prev = node;
       head.next = node;
       node.prev = head;
       
   }
   
   
}
class Node{
   Node next;
   Node prev;
    int key,val;
   
   Node(int key,int val){
       this.key = key;
       this.val = val;
   }
   
}
 
+1
gaurabhkumarjha271020012 weeks ago
// in c++
list<pair<int,int>>l;
unordered_map<int,list<pair<int, int>>::iterator> m;
    int size;
    LRUCache(int cap)
    {
        // code here
        size=cap;
    }
   int get(int key)
    {
        // your code here
        if (m.find(key) == m.end()) return -1;
        
        l.splice(l.begin(), l, m[key]);
        return m[key]->second;
    }
    
    //Function for storing key-value pair.
    void set(int key, int value)
    {
        // your code here 
         if (m.find(key) != m.end()){
             l.splice(l.begin(), l, m[key]);
             m[key]->second= value;
             return;   
         }
         
         if (l.size() == size){
             
             auto dkey= l.back().first;
              l.pop_back();
              m.erase(dkey);
         }
         
          l.push_front({key, value});
          m[key]= l.begin();
    }
0
joyrockok3 weeks ago
class LRUCache{  static class Node{ int key; int value; Node pre; Node next;  public Node(int key, int value) {  this.key = key;  this.value = value; }}static int N=0; // cached size// static Queue<Integer> cache;static HashMap<Integer, Node> map;static Node head, tail;
   //Constructor for initializing the cache capacity with the given value.public LRUCache(int cap) //LRUCache(int cap)   {       //code here    N = cap;         map = new HashMap<Integer, Node>();    head = new Node(0, 0);    tail = new Node(0, 0);    head.next = tail;    tail.pre = head;    head.pre = null;    tail.next = null;   }
public static void delNode(Node node) { node.pre.next = node.next; node.next.pre = node.pre;}public static void addNode(Node node) { node.next = head.next; node.next.pre = node; node.pre = head; head.next = node;}   //Function to return value corresponding to the key.   public static int get(int key)   {       // your code here    if(map.get(key) != null) {     Node node = map.get(key);     delNode(node); // node를 삭제 후     addNode(node); // 제일 끝에 넣는다. 즉 head에 넣는다.     return node.value;     } else {     return -1;    }   }
   //Function for storing key-value pair.   public static void set(int key, int value)   {       // your code here         if(map.get(key) != null) {     Node node = map.get(key);     node.value = value;     delNode(node);     addNode(node);    } else {     Node node = new Node(key, value);     if(map.size()>= N) {      map.remove(tail.pre.key);      map.put(key, node);      delNode(tail.pre);      addNode(node);     } else {      addNode(node);      map.put(key, node);     }    }   }}
0
kundankumardec163 weeks ago
Java implementation (using LinkedHashMap):
class LRUCache
{
    //Constructor for initializing the cache capacity with the given value.
    private static LinkedHashMap<Integer, Integer> map;
    private static int size;
    
    LRUCache(int cap) {
        //code here
        size = 0;
        map = new LinkedHashMap<>() {
            protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
                return size() > cap;
            }
        };
    }

    //Function to return value corresponding to the key.
    public static int get(int key)
    {
        // your code here
        int ans = map.getOrDefault(key, -1);
        if (ans != -1) {
            map.remove(key);
            set(key, ans);
        }
        return ans;
    }

    //Function for storing key-value pair.
    public static void set(int key, int value)
    {
        // your code here
        if (map.containsKey(key)) {
            map.remove(key);
        }
        map.put(key, value);
    }
}
0
swatisingh727774 weeks ago
class LRUCache
{  
    private:

    public:
    struct Node{
        int key;
        int val;
        Node* prev;
        Node* next;
        
        Node(int Key1 , int Val1){
            key = Key1;
            val = Val1;
        }
    };
    Node * head = new Node(-1,-1);
    Node * tail = new Node(-1,-1);
    int size;
    unordered_map<int , Node*>mp;
    
    
    LRUCache(int cap)
    {
        size = cap;
        head->next = tail;
        tail->prev = head;
    }
    void DelNode( Node* tempNode){
        Node* prev = tempNode->prev;
         Node* forward = tempNode->next;
         
         prev->next = forward;
         forward->prev = prev;
    }
    
    void InsNode(Node* tempNode){
        Node* temp = head->next;
        tempNode->next = temp;
        tempNode->prev = head;
        head->next = tempNode;
        temp->prev = tempNode;
    }
    int get(int key)
    {
        if(mp.find(key)!=mp.end()){
            Node* dummy = mp[key];
            int val = dummy->val;
            mp.erase(key);
            DelNode(dummy);
            InsNode(dummy);
            mp[key] = head->next;
            return val;
        }
        return -1;
    }
    
   
    void set(int key, int value)
    {
        if(mp.find(key)!=mp.end()){
            Node* dummy = mp[key];
            mp.erase(key);
            DelNode(dummy);
            
        }  
        if(mp.size()==size){
            mp.erase(tail->prev->key);
            DelNode(tail->prev);
        }
        InsNode(new Node(key , value));
        mp[key] = head->next;
    }
// O(1) time complexity
+1
akbhobhiya4 weeks ago
// Just Wanted to know where they have used the stack and queue in this  question. I have done this with the help of doubly linked list and unordered_map. bellow is the clean code of the implementation

class LRUCache
{
    private:

    public:
    //Constructor for initializing the cache capacity with the given value.
    class Node{
        public:
            int key;
            int data;
            Node *next,*prev;
            Node(int _key, int _data){
                key = _key;
                data= _data;
            }
    };
    Node *head = new Node(-1,-1);
    Node *tail = new Node(-1,-1);
    int cap;
    unordered_map<int,Node*>mp;
    LRUCache(int capacity){
        cap = capacity;
        head->next = tail;
        tail->prev = head;
    }
    void add(Node *node){
        Node *temp = head->next;
        head->next = node;
        node->prev = head;
        node->next = temp;
        temp->prev = node;
    }
    void remove(Node *node){
        Node *temp1 = node->prev;
        Node *temp2 = node->next;
        temp1->next=temp2;
        temp2->prev=temp1;
    }
    //Function to return value corresponding to the key.
    int get(int key){
        if(mp.find(key)==mp.end())return -1;
        Node *node = mp[key];
        int data = node->data;
        remove(node);
        mp.erase(key);
        add(node);
        mp[key]=node;
        return data;
    }
    //Function for storing key-value pair.
    void set(int key, int value){
        if(mp.find(key)!=mp.end()){
            Node *node = mp[key];
            mp.erase(key);
            remove(node);
        }
        if(mp.size()==cap){
            mp.erase(tail->prev->key);
            remove(tail->prev);
        }
        Node *newnode = new Node(key,value);
        add(newnode);
        mp[key]=newnode;
    }
};
0
abhishekshrivastav19201 month ago
I have used dummy head and tail pointer so that i need not to put extra condition.
    private:
        struct Node{
            int key;
            int value;
            Node *prev;
            Node *next;
            
            Node(int key,int value){
                this->key = key;
                this->value = value;
                
            }
        };
        
        Node *head = new Node(-1,-1);
        Node *tail = new Node(-1,-1);
        unordered_map<int,Node *> map;
        int capacity;
    
    public:
    //Constructor for initializing the cache capacity with the given value.
    LRUCache(int cap)
    {
        // code here
        capacity = cap;
        head->next = tail;
        tail->prev = head;
    }
    
    void removeNode(Node *node){
        
        Node *left = node->prev;
        Node *right = node->next;
        
        left->next = right;
        right->prev = left;
    }
    
    void addFirst(Node *node){
        Node *right = head->next;
        
        
        node->next = right;
        right->prev = node;
        
        head->next = node;
        node->prev = head;
        
    }
    //Function to return value corresponding to the key.
    int get(int key)
    {
        if(map.find(key) == map.end()){
            return -1;
        }
        
        
        Node *n = map[key];
        int ans = n->value;
        
        
        map.erase(key);
        
        removeNode(n);
        addFirst(n);
        
        map[key] = n;
        
        return ans;
    }
    
    //Function for storing key-value pair.
    void set(int key, int value)
    {
        if(map.find(key) != map.end()){
            removeNode(map[key]);
            map.erase(key);
            
        }
        
        if(map.size() == capacity){
            
            // remove last node
            Node *last = tail->prev;
            removeNode(last);
            map.erase(last->key);
        }
        
        
        Node *newNode = new Node(key,value);
        map[key] = newNode;
        addFirst(newNode);
    }
We strongly recommend solving this problem on your own before viewing its editorial. Do you still
                    want to view the editorial?
 Login to access your submissions. 

Problem


Contest

Reset the IDE using the second button on the top right corner.
Avoid using static/global variables in your code as your code is tested against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases does not guarantee the correctness of code. On submission, your code is tested against multiple test cases consisting of all possible corner cases and stress constraints.
You can access the hints to get an idea about what is expected of you as well as the final solution code.
You can view the solutions submitted by other users from the submission tab.