Leetcode: 146. LRU Cache

Question

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: getand 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 reached its capacity, it should invalidate the least recently used item before inserting a new item.
The cache is initialized with a positive capacity.
Follow up:
Could you do both operations in O(1) time complexity?
Example:

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

Note:

The point is to understand the feature of double linked list: move any node in constant time

The problem can be solved with a hashtable that keeps track of the keys and its values in the double linked list. One interesting property about double linked list is that the node can remove itself without other reference. In addition, it takes constant time to add and remove nodes from the head or tail.

One particularity about the double linked list that I implemented is that I create a pseudo head and tail to mark the boundary, so that we don’t need to check the NULL node during the update. This makes the code more concise and clean, and also it is good for the performance as well.

Solution:

class LRUCache {
	class DLNode {
		int key, val;
		DLNode prev, next;
	}

	public void removeNode(DLNode node) {
		node.prev.next = node.next;
		node.next.prev = node.prev;
		node.next = null;
		node.prev = null;
	}
	
	public void addToHead(DLNode node){
		node.next = head.next;
		node.next.prev = node;
		head.next = node;
		node.prev = head;
	}

	public DLNode removeTail() {
		DLNode node = tail.prev;
		node.prev.next = tail;
		tail.prev = node.prev;
		node.prev = null;
		node.next = null;
		return node;
	}
	
	Map<Integer, DLNode> cacheMap;
	DLNode head, tail;
	int capacity, count;
	public LRUCache(int capacity) {
		cacheMap = new HashMap<Integer, DLNode>();
		head = new DLNode();
		tail = new DLNode();
		head.prev = null;
		head.next = tail;
		tail.prev = head;
		tail.next = null;
		this.capacity = capacity;
		count = 0;
	}
	public int get(int key) {
		if (cacheMap.containsKey(key)) {
			DLNode node = cacheMap.get(key);
			removeNode(node);
			addToHead(node);
			return node.val;
		} else {
			return -1;
		}
	}
	public void put(int key, int value) {
		// here we need to consider the case of putting 
		// duplicated node
		DLNode node = new DLNode();
		node.key = key;
		node.val = value;
		if (!cacheMap.containsKey(key)) {
			cacheMap.put(key, node);
			addToHead(node);
			count++;
			if (count > capacity) {
				DLNode node = removeTail();
				cacheMap.remove(node.key);
				count--;
			}
		} else {
			// if the key is already in the map
            // then we need to update it to the new key value set
			removeNode(cacheMap.get(key));
			addToHead(node);
			cacheMap.replace(key, node);
		}
	}
	
}
/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值