1. 题目描述:
  2. 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制
  3. 实现 LRUCache 类:
  4. LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  5. int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  6. void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。
  7. 当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
  8. 示例:
  9. 输入:["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
  10. [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
  11. 输出:[null, null, null, 1, null, -1, null, -1, 3, 4]
  12. 解释:
  13. LRUCache lRUCache = new LRUCache(2);
  14. lRUCache.put(1, 1); // 缓存是 {1=1}
  15. lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
  16. lRUCache.get(1); // 返回 1
  17. lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
  18. lRUCache.get(2); // 返回 -1 (未找到)
  19. lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
  20. lRUCache.get(1); // 返回 -1 (未找到)
  21. lRUCache.get(3); // 返回 3
  22. lRUCache.get(4); // 返回 4
  23. var Node = function (key = null, val = null, next = null, pre = null) {
  24. //TODO
  25. }
  26. var LRUCache = function (capacity = 0) {
  27. //TODO
  28. this.capacity = capacity
  29. this.lru = {}
  30. this.sort = []
  31. };
  32. /**
  33. * @param {number} key
  34. * @return {number}
  35. */
  36. LRUCache.prototype.get = function (key) {
  37. //TODO
  38. if (this.lru[key] !== null) {
  39. let index = this.sort.findIndex(key)
  40. this.sort.splice(index, 1)
  41. this.sort.push(key)
  42. return this.lru[key]
  43. }
  44. return -1
  45. };
  46. /**
  47. * @param {number} key
  48. * @param {number} value
  49. * @return {void}
  50. */
  51. LRUCache.prototype.put = function (key, value) {
  52. //TODO
  53. if (this.sort.length >= this.capacity) {
  54. this.sort.unshift()
  55. this.sort.push(key)
  56. this.lru[key] =value
  57. } else {
  58. this.lru[key] = value
  59. this.sort.push(key)
  60. }
  61. };

我的回答

  1. var Node = function (key = null, val = null, next = null, pre = null) {
  2. //TODO
  3. }
  4. var LRUCache = function (capacity = 0) {
  5. //TODO
  6. this.capacity = capacity
  7. this.lru = {}
  8. this.sort = []
  9. };
  10. /**
  11. * @param {number} key
  12. * @return {number}
  13. */
  14. LRUCache.prototype.get = function (key) {
  15. //TODO
  16. if (this.lru[key] !== null) {
  17. let index = this.sort.findIndex(key)
  18. this.sort.splice(index, 1)
  19. this.sort.push(key)
  20. return this.lru[key]
  21. }
  22. return -1
  23. };
  24. /**
  25. * @param {number} key
  26. * @param {number} value
  27. * @return {void}
  28. */
  29. LRUCache.prototype.put = function (key, value) {
  30. //TODO
  31. if (this.sort.length >= this.capacity) {
  32. this.sort.unshift()
  33. this.sort.push(key)
  34. this.lru[key] =value
  35. } else {
  36. this.lru[key] = value
  37. this.sort.push(key)
  38. }
  39. };

参考回答

  1. //思路:用ES6提供的Map(hash表结构)来存储映射关系实现查询O(1),为了实现put操作O(1),用双向链表实现按访问顺序组织数据,然后通过尾指针获取最早的节点来当数据超过时进行删除。然后将链表节点作为Map的value存入
  2. // 关键点:边缘情况,特别是涉及头指针和尾指针移动的时候移动到的位置是否可能为空
  3. var Node = function (key = null, val = null, next = null, pre = null) {
  4. this.key = key
  5. this.val = val
  6. this.next = next
  7. this.pre = pre
  8. }
  9. var LRUCache = function (capacity = 0) {
  10. this.capacity = capacity
  11. this.map = new Map()
  12. this.head = null
  13. this.last = null
  14. };
  15. /**
  16. @param {number} key
  17. @return {number}
  18. */
  19. LRUCache.prototype.get = function (key) {
  20. if (this.map.has(key)) {
  21. let node = this.map.get(key)
  22. if (node !== this.head) {
  23. if (node === this.last) {
  24. this.last = node.pre
  25. }
  26. let preNode = node.pre
  27. let nextNode = node.next
  28. if (preNode)
  29. preNode.next = nextNode
  30. if (nextNode)
  31. nextNode.pre = preNode
  32. node.pre = null
  33. node.next = this.head
  34. this.head.pre = node
  35. this.head = node
  36. }
  37. return node.val
  38. }
  39. return -1
  40. };
  41. /**
  42. @param {number} key
  43. @param {number} value
  44. @return {void} */
  45. LRUCache.prototype.put = function (key, value) {
  46. if (this.map.has(key)) {
  47. let node = this.map.get(key)
  48. node.val = value
  49. if (node !== this.head) {
  50. if (node === this.last) {
  51. this.last = node.pre
  52. }
  53. let preNode = node.pre
  54. let nextNode = node.next
  55. if (preNode) preNode.next = nextNode
  56. if (nextNode) nextNode.pre = preNode
  57. node.pre = null
  58. node.next = this.head
  59. this.head.pre = node
  60. this.head = node
  61. }
  62. } else {
  63. if (this.capacity === 0) {
  64. this.map.delete(this.last.key)
  65. if (this.last.pre) { this.last.pre.next = null }
  66. this.last = this.last.pre
  67. }
  68. let newNode = new Node(key, value)
  69. this.map.set(key, newNode)
  70. if (this.head) {
  71. this.head.pre = newNode
  72. newNode.next = this.head
  73. } else {
  74. this.last = newNode
  75. }
  76. this.head = newNode
  77. if (this.capacity > 0) this.capacity--
  78. }
  79. };