2014年10月2日星期四

[Leetcode] 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.
链表题系列的最后一道题,要求设计一种在操作系统中用到的LRU Cache,核心思路是使用HashMap和双向链表来实现节点的开始查找以及删除和插入。注意一些小细节不要形成环或者节点为null。

public class LRUCache {
    
    public class CacheNode {
        int key, val;
        CacheNode prior, next;
        public CacheNode(int key, int val) {
            this.key = key;
            this.val = val;
            prior = null; next = null;
        }
    }
    
    CacheNode head, tail;
    int size, capacity;
    HashMap<Integer, CacheNode> map; // fast look up for a specific node

	public LRUCache(int capacity) {
        head = new CacheNode(0, 0);
        tail = head;
        size = 0;
        this.capacity = capacity;
        map = new HashMap<Integer, CacheNode>();
	}

	public int get(int key) {
		if(map.containsKey(key) == false) {
		    return -1;
		}
		else {
		    update(map.get(key));
		    return map.get(key).val;
		}
	}

	public void set(int key, int value) {
		if(map.containsKey(key) == true) {
		    CacheNode node = map.get(key);
		    node.val = value;
		    update(node);
		    map.put(key, node);
		}
		else {
		    CacheNode node = new CacheNode(key, value);
		    add(node);
		    map.put(key, node);
		}
	}
	
	private void update(CacheNode node) { // put the node at the back of a list
	    if(node == tail) return; // be careful with corner case
	    node.prior.next = node.next;
	    node.next.prior = node.prior;
	    node.prior = tail;
	    tail.next = node;
	    node.next = null;
	    tail = node;
	}
	
	private void add(CacheNode node) {
	    if(size < capacity) {
	        tail.next = node;
	        node.prior = tail;
	        tail = node;
	        size++;
	    }
	    else {
	        if(head.next == null) return;
	        if(tail == head.next) tail = head; // be careful with corner case
	        map.remove(head.next.key); // remove the head of the list
	        head.next = head.next.next;
	        if(head.next != null) head.next.prior = head;
	        tail.next = node;
	        node.prior = tail;
	        tail = node;
	    }
	}

}

没有评论:

发表评论