LRU (最近最少使用) 快取機制:時間複雜度O(1)
阿新 • • 發佈:2018-11-02
/** * Double Linked List * 用了一個特別的雙向的ListNode,有了head和tail,這樣就大大加快了速度。 * 主要加快的就是那個‘更新排位’的過程,找到item hashmap O(1), 做減法換位也都是O(1) * Overall O(1) *##### 巧妙點 * 1. head和tail特別巧妙:除掉頭和尾,和加上頭和尾,就都特別快。 * 2. 用雙向的pointer: pre和next, 當需要除掉任何一個node的時候,只要知道要除掉哪一個, * 直接把node.pre和node.next耐心連起來就好了,node就自然而然的斷開不要了。 * 一旦知道怎麼解決了,就不是很特別,並不是難寫的演算法: * moveToHead() * insertHead() * remove() **/ public class LRUCache { class DoubleLinkedListNode { int key, val; DoubleLinkedListNode next,prev; public DoubleLinkedListNode(int key, int val){ this.key = key; this.val = val; next = null; prev = null; } } public int capacity; public HashMap<Integer, DoubleLinkedListNode> map; public DoubleLinkedListNode head, tail; public LRUCache(int capacity) { this.capacity = capacity; this.map = new HashMap<>(); this.head = new DoubleLinkedListNode(-1, -1); this.tail = new DoubleLinkedListNode(-1, -1); head.next = tail; head.prev = tail; tail.next = head; tail.prev = head; } public int get(int key) { if(!map.containsKey(key)) { return -1; } DoubleLinkedListNode node = map.get(key); moveToHead(node); return node.val; } public void put(int key, int value) { if (map.containsKey(key)) { map.get(key).val = value; moveToHead(map.get(key)); } else { DoubleLinkedListNode node = new DoubleLinkedListNode(key, value); if (map.size() >= this.capacity) { DoubleLinkedListNode rm = tail.prev; remove(rm); map.remove(rm.key); } insertHead(node); map.put(key, node); } } public void moveToHead(DoubleLinkedListNode node) { remove(node); insertHead(node); } //Helper functions /* Put node to front, where the latest item is at. */ public void insertHead(DoubleLinkedListNode node) { DoubleLinkedListNode next = head.next; head.next = node; node.prev = head; node.next = next; next.prev = node; } /* Find front and end, link them. */ public void remove(DoubleLinkedListNode node) { DoubleLinkedListNode front = node.prev; DoubleLinkedListNode end = node.next; front.next = end; end.prev = front; } }