当前位置:   article > 正文

LRU缓存-LeetCode146_请你设计并实现一个满lru缓存约束的数据结构,实现lrucache类

请你设计并实现一个满lru缓存约束的数据结构,实现lrucache类

(一)题目描述

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity): 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key): 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value): 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

(二)解题思路

(1)LRU:Least Recently Used :最近最少使用算法(操作系统中一种常用页面置换算法)。

(2)如何控制最近最少使用的键值对在内存达到最大时被删除?每次在访问完键值对后都将其移到链表头部,在内存达到最大时删除链表尾部的节点即可。

(3)该题相当于是手写LinkedHashMap实现的底层源码。

(三)代码实现

  1. package promble;
  2. import java.util.HashMap;
  3. import java.util.LinkedHashMap;
  4. /**
  5. * @author 一休
  6. * @version 1.0
  7. * @create 2022-04-11 16:59
  8. */
  9. //相当于实现一个LRUcache类(也相当于自己实现了LinkedHashMap)
  10. //自己定义一个双向链表
  11. //手写实现LinkedHashMap
  12. class LinkedNode {
  13. int key;
  14. int value;
  15. LinkedNode prev;
  16. LinkedNode next;
  17. public LinkedNode() {
  18. }
  19. public LinkedNode(int key, int value) {
  20. this.key = key;
  21. this.value = value;
  22. }
  23. }
  24. class LRUCache {
  25. //hashMap中的value为自己定义的一个class节点,该节点有key,value,指向前后的指针
  26. HashMap<Integer, LinkedNode> hashMap;
  27. int size;
  28. int capacity;
  29. LinkedNode head;
  30. LinkedNode tail;
  31. public LRUCache(int capacity) {
  32. hashMap = new HashMap<>(capacity);
  33. size=0;
  34. this.capacity = capacity;
  35. head = new LinkedNode();
  36. tail = new LinkedNode();
  37. head.next = tail;
  38. tail.prev = head;
  39. }
  40. public int get(int key) {
  41. //如果获取到当前元素
  42. LinkedNode node = hashMap.get(key);
  43. if (node != null) {
  44. //去除当前元素
  45. remove(node);
  46. //添加到头部
  47. add(node);
  48. //返回index;
  49. return node.value;
  50. }
  51. return -1;
  52. //添加到头部
  53. //返回-1
  54. }
  55. public void put(int key, int value) {
  56. LinkedNode node = hashMap.get(key);
  57. if (node != null) {
  58. node.value = value;
  59. //删除当前节点
  60. remove(node);
  61. //移至头部
  62. add(node);
  63. } else {
  64. LinkedNode newNode = new LinkedNode(key, value);
  65. hashMap.put(key, newNode);
  66. add(newNode);
  67. size++;
  68. if (size > capacity) {
  69. LinkedNode removedNode = removeTail();
  70. hashMap.remove(removedNode.key);
  71. }
  72. }
  73. }
  74. private void add(LinkedNode node) {
  75. node.next = head.next;
  76. head.next = node;
  77. node.next.prev = node;
  78. node.prev = head;
  79. }
  80. private void remove(LinkedNode node) {
  81. node.prev.next = node.next;
  82. node.next.prev=node.prev;
  83. }
  84. private LinkedNode removeTail() {
  85. LinkedNode prev = tail.prev;
  86. remove(prev);
  87. return prev;
  88. }
  89. }

(四)小tips:设置伪头结点和伪尾结点,使所有节点都是进行同样的处理

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/491692
推荐阅读
相关标签
  

闽ICP备14008679号