Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and put
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.put(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.
Follow up:
Could you do both operations in O(1) time complexity?
1 public class LRUCache { 2 // double linked list node 3 public class Node 4 { 5 public Node left; 6 public Node right; 7 public int key; 8 public int val; 9 10 public Node(int k, int v) 11 { 12 key = k; 13 val = v; 14 } 15 } 16 17 private Dictionary<int, Node> dict = new Dictionary<int, Node>(); 18 private int capacity = 0; 19 private Node head = null; 20 private Node tail = null; 21 22 public LRUCache(int capacity) { 23 this.capacity = capacity; 24 this.head = new Node(-1, -1); 25 this.tail = new Node(-1, -1); 26 27 this.head.right = this.tail; 28 this.tail.left = this.head; 29 } 30 31 public int Get(int key) { 32 if (dict.ContainsKey(key)) 33 { 34 var n = dict[key]; 35 36 MoveToHead(n); 37 38 return n.val; 39 } 40 else 41 { 42 return -1; 43 } 44 } 45 46 private void MoveToHead(Node n, bool newNode = false) 47 { 48 if (!newNode) 49 { 50 // remove n from current position 51 n.left.right = n.right; 52 n.right.left = n.left; 53 } 54 55 // move to the head 56 var right = this.head.right; 57 n.right = right; 58 right.left = n; 59 this.head.right = n; 60 n.left = this.head; 61 } 62 63 public void Put(int key, int value) { 64 if (dict.ContainsKey(key)) 65 { 66 var n = dict[key]; 67 n.val = value; 68 69 MoveToHead(n); 70 } 71 else 72 { 73 var n = new Node(key, value); 74 dict[key] = n; 75 MoveToHead(n, true); 76 77 // remove the last node (least used) if necessary 78 if (dict.Count > this.capacity) 79 { 80 dict.Remove(this.tail.left.key); 81 82 var p = this.tail.left.left; 83 p.right = this.tail; 84 this.tail.left = p; 85 } 86 } 87 } 88 } 89 90 /** 91 * Your LRUCache object will be instantiated and called as such: 92 * LRUCache obj = new LRUCache(capacity); 93 * int param_1 = obj.Get(key); 94 * obj.Put(key,value); 95 */