LRU Cache

Question

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.

set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Analysis:

The basic idea is using LinkedList + HashMap

HashMap is used to store the key-value pairs and LinkedList is used as a queue to record the order of recent used key-value

We can implement our own LinkedList structure or using LinkedHashMap from Java Collection.

Solution Using LinkedHashMap

public class LRUCache {
    private int capacity;
    private LinkedHashMap<Integer,Integer> map;
    public LRUCache(int capacity) {
        this.capacity=capacity;
        this.map=new LinkedHashMap<Integer,Integer>();
    }

    public int get(int key) {
        if(map.containsKey(key)) {
            int res=map.get(key);
            map.remove(key);
            map.put(key,res);
            return res;
        }
        else return -1;
    }

    public void set(int key, int value) {
        if(map.containsKey(key)) map.remove(key);
        if(capacity>0){
            if(map.size()==capacity) map.remove(map.keySet().iterator().next());
            map.put(key,value);
        }
    }
}

Solution Implemented LinkedList

public class LRUCache {
    class Node{
        int key;
        int value;
        Node next, pre;
        Node(int key, int value){
            this.key=key;
            this.value=value;
        }
    }

    Node cache;//head node of the cache 
    HashMap<Integer,Node> dic;
    int capacity;
    public LRUCache(int capacity) {
        cache=null;
        dic=new HashMap<Integer,Node>();
        this.capacity=capacity;
    }

    public int get(int key) {
        if(dic.containsKey(key)) {
            flushCache(key);
            return dic.get(key).value;
        }
        else return -1;
    }

    public void set(int key, int value) {
        if(capacity<=0) return;
        if(dic.containsKey(key)) {
            dic.get(key).value=value;
            flushCache(key);
        }else{
            if(dic.size()==capacity){//when cache is full, evict the least recently used node
                if(cache.pre.equals(cache)){//when there is only one node
                    dic.remove(cache.key);
                    cache=null;
                }else{
                    dic.remove(cache.pre.key);
                    cache.pre.pre.next=null;
                    cache.pre=cache.pre.pre;

                }
            }
            //append the new node
            Node head=new Node(key,value);
            if(cache==null){
                head.pre=head;
                head.next=null;
                cache=head;
            }else{
                head.pre=cache.pre;
                cache.pre=head;
                head.next=cache;
                cache=head;
            }
            dic.put(key,head);
        }
    }

    public void flushCache(int key){//flush cache means to update the state of the recently used nodec
        Node toBeHead=dic.get(key);
        if(!toBeHead.equals(cache)){
            toBeHead.pre.next=toBeHead.next;
            if(toBeHead.next!=null) toBeHead.next.pre=toBeHead.pre;
            toBeHead.pre=(toBeHead.next==null)?toBeHead.pre:cache.pre;
            cache.pre=toBeHead;
            toBeHead.next=cache;
            cache=toBeHead;
        }
    }
}

Python Version

from collections import OrderedDict

class LRUcache(object):
    def __init__(self, capacity):
        self.capacity = capacity
        self.cache_map = OrderedDict()

    def get(self, k):
        if k in self.cache_map:
            ans = self.cache_map[k]
            del self.cache_map[k]
            self.cache_map[k] = ans
            return ans
        else:
            return -1

    def set(self, k, v):
        if k in self.cache_map:
            del self.cache_map[k]
        if len(self.cache_map) == self.capacity:
            self.cache_map.popitem(last=False)
        self.cache_map[k] = v

results matching ""

    No results matching ""