1. 程式人生 > 實用技巧 >每天1題演算法題(11)- LRU快取機制

每天1題演算法題(11)- LRU快取機制

運用你所掌握的資料結構,設計和實現一個 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; } }