LRU Cache

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.

Solution:

  1. public class LRUCache {
  2. int capacity;
  3. Map<Integer, ListNode> map;
  4. ListNode head;
  5. ListNode tail;
  6. public LRUCache(int cap) {
  7. capacity = cap;
  8. map = new HashMap<>();
  9. head = new ListNode(0, 0);
  10. tail = new ListNode(0, 0);
  11. head.next = tail;
  12. tail.prev = head;
  13. }
  14. public int get(int key) {
  15. if (!map.containsKey(key)) {
  16. return -1;
  17. }
  18. ListNode node = map.get(key);
  19. promote(node);
  20. return node.val;
  21. }
  22. public void set(int key, int val) {
  23. ListNode node;
  24. if (map.containsKey(key)) {
  25. node = map.get(key);
  26. promote(node);
  27. node.val = val;
  28. return;
  29. }
  30. if (map.size() == capacity) {
  31. ListNode last = tail.prev;
  32. map.remove(last.key);
  33. remove(last);
  34. }
  35. node = new ListNode(key, val);
  36. map.put(key, node);
  37. insert(node);
  38. }
  39. void remove(ListNode node) {
  40. node.prev.next = node.next;
  41. node.next.prev = node.prev;
  42. }
  43. void insert(ListNode node) {
  44. node.prev = head;
  45. node.next = head.next;
  46. head.next.prev = node;
  47. head.next = node;
  48. }
  49. void promote(ListNode node) {
  50. remove(node);
  51. insert(node);
  52. }
  53. class ListNode {
  54. int key;
  55. int val;
  56. ListNode prev = null;
  57. ListNode next = null;
  58. public ListNode(int k, int v) {
  59. key = k;
  60. val = v;
  61. }
  62. }
  63. }