哈希表 + 双向链表

146. LRU 缓存机制

  • 新访问, 保存顶部
  • 若存在, 先移除
  • 若容量不足, 先移除底部

image.png
简单实现

  1. /**
  2. * @param {number} capacity
  3. */
  4. var LRUCache = function(capacity) {
  5. this.capacity = capacity;
  6. this.hashTable = new Map();
  7. this.arr = [];
  8. };
  9. /**
  10. * @param {number} key
  11. * @return {number}
  12. */
  13. LRUCache.prototype.get = function(key) {
  14. if (!this.hashTable.has(key)) return -1;
  15. // hash不变, cache中移动key至顶部
  16. let index = this.arr.indexOf(key);
  17. this.arr.splice(index, 1);
  18. this.arr.unshift(key)
  19. return this.hashTable.get(key)
  20. };
  21. /**
  22. * @param {number} key
  23. * @param {number} value
  24. * @return {void}
  25. */
  26. LRUCache.prototype.put = function(key, value) {
  27. // 已存在, hash中set进行重写
  28. if (this.hashTable.has(key)) {
  29. let index = this.arr.indexOf(key);
  30. this.arr.splice(index, 1)
  31. this.arr.unshift(key)
  32. this.hashTable.set(key, value)
  33. return;
  34. }
  35. // 容量不足
  36. if (this.arr.length >= this.capacity) {
  37. let tail = this.arr.pop()
  38. this.hashTable.delete(tail)
  39. }
  40. this.arr.unshift(key)
  41. this.hashTable.set(key, value)
  42. };
  43. /**
  44. * Your LRUCache object will be instantiated and called as such:
  45. * var obj = new LRUCache(capacity)
  46. * var param_1 = obj.get(key)
  47. * obj.put(key,value)
  48. */

测试用例

  1. ["LRUCache","put","put","get","put","get","put","get","get","get"]
  2. [[2],[1,1],[2,2],[1],[3,3],[2],[4,4],[1],[3],[4]]
  3. ["LRUCache","put","put","get","put","put","get"]
  4. [[2],[2,1],[2,2],[2],[1,1],[4,1],[2]]

哈希表+双链表实现

  1. function DLinkedNode(key=null, value=null) {
  2. this.key = key;
  3. this.value = value;
  4. this.prev = null;
  5. this.next = null;
  6. }
  7. /**
  8. * @param {number} capacity
  9. */
  10. var LRUCache = function(capacity) {
  11. this.capacity = capacity;
  12. this.hashTable = new Map();
  13. // 伪头部和伪尾部节点
  14. this.head = new DLinkedNode();
  15. this.tail = new DLinkedNode();
  16. this.head.next = this.tail;
  17. this.tail.prev = this.head;
  18. this.size = 0;
  19. };
  20. /**
  21. * @param {number} key
  22. * @return {number}
  23. */
  24. LRUCache.prototype.get = function(key) {
  25. if (!this.hashTable.has(key)) return -1;
  26. // hash不变, cache中移动key至顶部
  27. let node = this.hashTable.get(key);
  28. this.removeNode(node);
  29. this.addNode(node)
  30. return node.value;
  31. };
  32. /**
  33. * @param {number} key
  34. * @param {number} value
  35. * @return {void}
  36. */
  37. LRUCache.prototype.put = function(key, value) {
  38. // 已存在, hash中set进行重写
  39. if (this.hashTable.has(key)) {
  40. let node = this.hashTable.get(key);
  41. node.value = value;
  42. this.get(key)
  43. return;
  44. }
  45. // 容量不足
  46. if (this.size >= this.capacity) {
  47. let tail = this.removeTail();
  48. this.hashTable.delete(tail.key)
  49. this.size -= 1;
  50. }
  51. let node = new DLinkedNode(key, value)
  52. this.addNode(node)
  53. this.hashTable.set(key, node)
  54. this.size += 1;
  55. };
  56. LRUCache.prototype.removeNode = function (node) {
  57. node.prev.next = node.next;
  58. node.next.prev = node.prev;
  59. }
  60. /**
  61. * 默认添加在顶部
  62. */
  63. LRUCache.prototype.addNode = function (node) {
  64. node.prev = this.head;
  65. node.next = this.head.next;
  66. // head
  67. this.head.next.prev = node;
  68. this.head.next = node;
  69. }
  70. LRUCache.prototype.removeTail = function () {
  71. let node = this.tail.prev;
  72. this.removeNode(node)
  73. return node;
  74. }
  75. /**
  76. * Your LRUCache object will be instantiated and called as such:
  77. * var obj = new LRUCache(capacity)
  78. * var param_1 = obj.get(key)
  79. * obj.put(key,value)
  80. */