Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and 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
思路:
可以直接使用LinkHashMap實現LRU。
LinkedHashMap實現原理基於HashMap+雙向鏈表,這里自己實現一遍。
題解:
import java.util.HashMap; class LRUCache { class Node { int key; int value; Node prev; Node next; } /** * 向雙向鏈表加入新節點 * 加入到表頭 */ private void addNode(Node node) { node.prev = head; node.next = head.next; head.next.prev = node; head.next = node; } /** * 刪除節點 */ private void removeNode(Node node) { node.prev.next = node.next; node.next.prev = node.prev; } /** * 刪除表尾節點 */ private Node popTail() { Node node = tail.prev; removeNode(node); return node; } /** * 移動到表頭 * 1.刪除原節點 * 2.在表頭插入原節點 */ private void moveToHead(Node node) { removeNode(node); addNode(node); } private int capacity; private int size; private HashMap<Integer, Node> cache; private Node head; private Node tail; public LRUCache(int capacity) { this.capacity = capacity; this.size = 0; cache = new HashMap<>(); head = new Node(); tail = new Node(); head.next = tail; tail.prev = head; } /** * get()操作 * 如果key對應的value不存在,返回-1 * 如果存在,則獲取值,並將節點移動到表頭 */ public int get(int key) { Node node = cache.get(key); if (node == null) return -1; moveToHead(node); return node.value; } /** * put()操作 * 如果key不存在,則新建節點,將節點加入cache map,放置到表頭,size+1 * 如果size>capacity,要去除表尾節點,並從cache中刪除,size-1 * 如果key存在,將該節點的值更新,並移動到表頭 */ public void put(int key, int value) { Node node = cache.get(key); if (node == null) { node = new Node(); node.key = key; node.value = value; cache.put(key, node); addNode(node); size++; if (size > capacity) { Node del = popTail(); cache.remove(del.key); size--; } } else { node.value = value; moveToHead(node); } } public static void main(String[] args) { LRUCache lruCache = new LRUCache(2); lruCache.put(1, 1); lruCache.put(2, 2); lruCache.get(1); lruCache.put(3, 3); lruCache.get(2); lruCache.put(4, 4); lruCache.get(1); lruCache.get(3); lruCache.get(4); } } /** * 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); */