本題是leetcode,地址:146. LRU緩存機制java
運用你所掌握的數據結構,設計和實現一個 LRU (最近最少使用) 緩存機制。它應該支持如下操做: 獲取數據 get 和 寫入數據 put 。node
獲取數據 get(key) - 若是關鍵字 (key) 存在於緩存中,則獲取關鍵字的值(老是正數),不然返回 -1。
寫入數據 put(key, value) - 若是關鍵字已經存在,則變動其數據值;若是關鍵字不存在,則插入該組「關鍵字/值」。當緩存容量達到上限時,它應該在寫入新數據以前刪除最久未使用的數據值,從而爲新的數據值留出空間。算法進階:緩存
你是否能夠在 O(1) 時間複雜度內完成這兩種操做?數據結構
示例:this
LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );設計
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 該操做會使得關鍵字 2 做廢
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 該操做會使得關鍵字 1 做廢
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4code
LRU 算法其實是讓你設計數據結構:首先要接收一個 capacity 參數做爲緩存的最大容量,而後實現兩個 API,一個是 put(key, val) 方法存入鍵值對,另外一個是 get(key) 方法獲取 key 對應的 val,若是 key 不存在則返回 -1。ci
注意哦,get 和 put 方法必須都是 O(1)O(1) 的時間複雜度,在雙向鏈表的實現中,使用一個僞頭部(dummy head)和僞尾部(dummy tail)標記界限,這樣在添加節點時添加到頭節點,刪除時,刪除尾節點的數據。leetcode
class LRUCache { class MyNode { int key; int value; MyNode prev; MyNode next; public MyNode() { } public MyNode(int _key, int _value) { key = _key; value = _value; } } private int capacity; private int size; private Map<Integer, MyNode> cache = new HashMap<>(); private MyNode head, tail; public LRUCache(int capacity) { this.size = 0; this.capacity = capacity; this.head = new MyNode(); this.tail = new MyNode(); head.next = tail; tail.prev = head; } public int get(int key) { MyNode node = cache.get(key); if (node == null) { return -1; } else { // 更換到頭節點 moveToHead(node); return node.value; } } private void moveToHead(MyNode node) { removeNode(node); addToHead(node); } public void put(int key, int value) { MyNode node = cache.get(key); if (node == null) { node = new MyNode(key, value); addToHead(node); size++; if (size > capacity) { MyNode tail = removeTail(); cache.remove(tail.key); size--; } cache.put(key,node); } else { node.value = value; moveToHead(node); } } private void addToHead(MyNode node) { node.prev = head; node.next = head.next; head.next.prev = node; head.next = node; } private MyNode removeTail() { MyNode node = tail.prev; removeNode(node); return node; } private void removeNode(MyNode node) { node.prev.next = node.next; node.next.prev = node.prev; } } /** * 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); */