wayetan
1/7/2014 - 8:04 AM

LRU Cache

LRU Cache

/**
 * 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.
 */

public class LRUCache {
    private HashMap<Integer, LRUCache.DoubleLinkedListNode> map = new HashMap<Integer, LRUCache.DoubleLinkedListNode>();
    private DoubleLinkedListNode head;
    private DoubleLinkedListNode end;
    private int capacity;
    private int len;
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.len = 0;
    }
    
    public int get(int key) {
        if(this.map.containsKey(key)){
            // move this referred frame to the front;
            removeNode(this.map.get(key));
            setHead(this.map.get(key));
            return this.map.get(key).val;
        }else{
            return -1;
        }
    }
    
    public void set(int key, int value) {
        if(this.map.containsKey(key)){
            // if the map contains this frame, set the value, move it to the front. 
            DoubleLinkedListNode curr = this.map.get(key);
            curr.val = value;
            removeNode(curr);
            setHead(curr);
        }else{
            // if the map doesn't contain this frame, insert it.
            DoubleLinkedListNode curr = new DoubleLinkedListNode(key, value);
            if(this.len < this.capacity){
                setHead(curr);
                this.map.put(key, curr);
                this.len++;
            }else{
                this.map.remove(this.end.key);
                this.end = this.end.pre;
                if(this.end != null){
                    this.end.post = null;
                }
                setHead(curr);
                this.map.put(key, curr);
            }
        }
    }
    
    private class DoubleLinkedListNode {
        public int val;
        public int key;
        public DoubleLinkedListNode pre;
        public DoubleLinkedListNode post;
        // constuctor
        public DoubleLinkedListNode(int key, int value){
            this.val = value;
            this.key = key;
        }
    }
    
    private void setHead(DoubleLinkedListNode node){
        node.post = this.head;
        node.pre = null;
        if(this.head != null){
            this.head.pre = node;
        }
        this.head = node;
        if(this.end == null){
            this.end = node;
        }
    }
    
    private void removeNode(DoubleLinkedListNode node){
        DoubleLinkedListNode curr = node;
        DoubleLinkedListNode pre = curr.pre;
        DoubleLinkedListNode post = curr.post;
        if(pre != null){
            pre.post = post;
        }else{
            this.head = post;
        }
        if(post != null){
            post.pre = pre;
        }else{
            this.end = pre;
        }
    }
}