每天1題演算法題(11)- LRU快取機制
阿新 • • 發佈:2020-10-29
運用你所掌握的資料結構,設計和實現一個 LRU (最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get 和 寫入資料 put 。
獲取資料 get(key) - 如果關鍵字 (key) 存在於快取中,則獲取關鍵字的值(總是正數),否則返回 -1。
寫入資料 put(key, value) - 如果關鍵字已經存在,則變更其資料值;如果關鍵字不存在,則插入該組「關鍵字/值」。當快取容量達到上限時,它應該在寫入新資料之前刪除最久未使用的資料值,從而為新的資料值留出空間。
示例:
解
方法一:雜湊表 + 雙向連結串列
雙向連結串列按照被使用的順序儲存了這些鍵值對,靠近頭部的鍵值對是最近使用的,而靠近尾部的鍵值對是最久未使用的。
雜湊表即為普通的雜湊對映(HashMap),通過快取資料的鍵對映到其在雙向連結串列中的位置。
class LRUCache { private int capacity; private int size; private Map<Integer, DLinkedNode> cache = new HashMap(); private DLinkedNode head,tail; class DLinkedNode { int key; int value; DLinkedNode prev; DLinkedNode next;public DLinkedNode() {} public DLinkedNode(int _key, int _value) {key = _key; value = _value;} } public LRUCache(int capacity) { this.capacity = capacity; head = new DLinkedNode(); tail = new DLinkedNode(); head.next = tail; tail.prev = head; }public int get(int key) { DLinkedNode node = cache.get(key); if(node == null) { return -1; } else { moveToHead(node); return node.value; } } public void put(int key, int value) { DLinkedNode node = cache.get(key); if(node == null) { DLinkedNode newNode = new DLinkedNode(key, value); cache.put(key, newNode); addToHead(newNode); size++; if(size > capacity) { DLinkedNode tailNode = removeTail(); cache.remove(tailNode.key); size --; } } else { node.value = value; moveToHead(node); } } private void addToHead(DLinkedNode node) { DLinkedNode preSecondNode = head.next; head.next = node; node.prev = head; preSecondNode.prev = node; node.next = preSecondNode; } private void moveToHead(DLinkedNode node) { DLinkedNode appendPrevNode = node.prev; DLinkedNode appendNextNode = node.next; appendPrevNode.next = appendNextNode; appendNextNode.prev = appendPrevNode; DLinkedNode preSecondNode = head.next; head.next = node; node.prev = head; node.next = preSecondNode; preSecondNode.prev = node; } private DLinkedNode removeTail() { DLinkedNode tailNode = tail.prev; DLinkedNode pretailNode = tailNode.prev; tail.prev = pretailNode; pretailNode.next = tail; return tailNode; } }