[Leetcode] LRU cache
Problem:
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(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.
Thought:
Use a HashMap along with a doubly linked list to achieve the O(1) running time for both get and set.
package leetcode_Java; import java.util.Comparator; import java.util.HashMap; import java.util.PriorityQueue; public class LRUCache { HashMap <Integer, ListEntry> map = new HashMap<Integer, ListEntry>(); DoublyLinkedList list; public LRUCache(int capacity) { list = new DoublyLinkedList(capacity, map); } public int get(int key) { ListEntry entry = map.get(key); if(entry == null){ return -1; }else{ list.MoveToHead(entry); return entry.value; } } public void set(int key, int value) { ListEntry entry = map.get(key); if(entry == null){ ListEntry newEntry = new ListEntry(null, null, value, key); map.put(key, newEntry); list.Add(newEntry); }else{ entry.value = value; list.MoveToHead(entry); } } } class DoublyLinkedList{ ListEntry head; ListEntry tail; int capacity; int currentSize; HashMap <Integer, ListEntry> map; public DoublyLinkedList(int capacity, HashMap <Integer, ListEntry> map){ this.capacity = capacity; this.currentSize = 0; this.map = map; } public void Add(ListEntry entry){ if(currentSize < capacity){ if(head == null){ head = entry; tail = entry; }else{ head.prev = entry; entry.next = head; head = entry; } currentSize++; }else{ head.prev = entry; entry.next = head; head = entry; //remove tail map.remove(tail.key); tail = tail.prev; tail.next = null; } } //Assume that entry has already existed somewhere in the doubly linked list public void MoveToHead(ListEntry entry){ if(entry == head){ return; }else if(entry == tail){ tail = entry.prev; entry.prev.next = null; }else{ // in the middle entry.prev.next = entry.next; entry.next.prev = entry.prev; } head.prev = entry; entry.next = head; entry.prev = null; head = entry; } } // Node type of a doubly linked list class ListEntry{ ListEntry prev; ListEntry next; int value; int key; public ListEntry(ListEntry prev, ListEntry next, int value, int key) { super(); this.prev = prev; this.next = next; this.value = value; this.key = key; } }