• 146.LRU缓存


    题目:

    请你设计并实现一个满足  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

    LCR 031. LRU 缓存 - 力扣(LeetCode)

    题解:

    思路:

    用一个哈希表和一个双端队列,队列里面存储key,哈希存value。get时把对应的key删除,放在队首。put时有旧的则删掉,size够了把队列的最后一个删掉。然后加入,并且覆盖哈希表里面的值。

    代码:

    1. class LRUCache {
    2. private int capacity;
    3. private Map cache;
    4. private Deque queue;
    5. public LRUCache(int capacity) {
    6. this.capacity=capacity;
    7. this.cache=new HashMap<>();
    8. this.queue=new LinkedList<>();
    9. }
    10. public int get(int key) {
    11. if(cache.containsKey(key)){
    12. queue.remove(key);
    13. queue.offerFirst(key);
    14. return cache.get(key);
    15. }
    16. return -1;
    17. }
    18. public void put(int y, int value) {
    19. if(cache.containsKey(y)){
    20. queue.remove(y);
    21. }
    22. if(queue.size()==capacity){
    23. Integer oldKey=queue.pollLast();
    24. cache.remove(oldKey);
    25. }
    26. cache.put(y,value);
    27. queue.offerFirst(y);
    28. }
    29. }

    1. class Node {
    2. int data;
    3. Node next;
    4. Node prev;
    5. Node(int data) {
    6. this.data = data;
    7. }
    8. }
    9. class MyDeque {
    10. private Node front;
    11. private Node rear;
    12. private int size;
    13. public MyDeque() {
    14. front = null;
    15. rear = null;
    16. size = 0;
    17. }
    18. // 向队列前端添加元素
    19. public void offerFirst(int data) {
    20. Node newNode = new Node(data);
    21. if (isEmpty()) {
    22. front = newNode;
    23. rear = newNode;
    24. } else {
    25. newNode.next = front;
    26. front.prev = newNode;
    27. front = newNode;
    28. }
    29. size++;
    30. }
    31. // 移除指定元素
    32. public void remove(int key) {
    33. Node current = front;
    34. while (current != null) {
    35. if (current.data == key) {
    36. if (current == front) {
    37. pollFirst();
    38. } else if (current == rear) {
    39. pollLast();
    40. } else {
    41. current.prev.next = current.next;
    42. current.next.prev = current.prev;
    43. size--;
    44. }
    45. return;
    46. }
    47. current = current.next;
    48. }
    49. return;
    50. }
    51. // 从队列尾部移除元素
    52. public int pollLast() {
    53. if (isEmpty()) {
    54. return -1;
    55. }
    56. int removedData = rear.data;
    57. if (size == 1) {
    58. front = null;
    59. rear = null;
    60. } else {
    61. rear = rear.prev;
    62. rear.next = null;
    63. }
    64. size--;
    65. return removedData;
    66. }
    67. // 从队列前端移除元素
    68. public int pollFirst() {
    69. if (isEmpty()) {
    70. return -1;
    71. }
    72. int removedData = front.data;
    73. if (size == 1) {
    74. front = null;
    75. rear = null;
    76. } else {
    77. front = front.next;
    78. front.prev = null;
    79. }
    80. size--;
    81. return removedData;
    82. }
    83. // 判断队列是否为空
    84. public boolean isEmpty() {
    85. return size == 0;
    86. }
    87. // 获取队列大小
    88. public int size() {
    89. return size;
    90. }
    91. }

    完整的双端队列:

    1. class Node {
    2. int data;
    3. Node next;
    4. Node prev;
    5. Node(int data) {
    6. this.data = data;
    7. }
    8. }
    9. public class MyDeque {
    10. private Node front;
    11. private Node rear;
    12. private int size;
    13. public MyDeque() {
    14. front = null;
    15. rear = null;
    16. size = 0;
    17. }
    18. // 向队列前端添加元素
    19. public void addFirst(int data) {
    20. Node newNode = new Node(data);
    21. if (isEmpty()) {
    22. front = newNode;
    23. rear = newNode;
    24. } else {
    25. newNode.next = front;
    26. front.prev = newNode;
    27. front = newNode;
    28. }
    29. size++;
    30. }
    31. // 向队列尾部添加元素
    32. public void addLast(int data) {
    33. Node newNode = new Node(data);
    34. if (isEmpty()) {
    35. front = newNode;
    36. rear = newNode;
    37. } else {
    38. rear.next = newNode;
    39. newNode.prev = rear;
    40. rear = newNode;
    41. }
    42. size++;
    43. }
    44. // 从队列前端移除元素
    45. public int removeFirst() {
    46. if (isEmpty()) {
    47. throw new IllegalStateException("队列为空");
    48. }
    49. int removedData = front.data;
    50. if (size == 1) {
    51. front = null;
    52. rear = null;
    53. } else {
    54. front = front.next;
    55. front.prev = null;
    56. }
    57. size--;
    58. return removedData;
    59. }
    60. // 从队列尾部移除元素
    61. public int removeLast() {
    62. if (isEmpty()) {
    63. throw new IllegalStateException("队列为空");
    64. }
    65. int removedData = rear.data;
    66. if (size == 1) {
    67. front = null;
    68. rear = null;
    69. } else {
    70. rear = rear.prev;
    71. rear.next = null;
    72. }
    73. size--;
    74. return removedData;
    75. }
    76. // 移除指定元素
    77. public void remove(int key) {
    78. Node current = front;
    79. while (current != null) {
    80. if (current.data == key) {
    81. if (current == front) {
    82. removeFirst();
    83. } else if (current == rear) {
    84. removeLast();
    85. } else {
    86. current.prev.next = current.next;
    87. current.next.prev = current.prev;
    88. size--;
    89. }
    90. return;
    91. }
    92. current = current.next;
    93. }
    94. throw new IllegalArgumentException("队列中没有该元素");
    95. }
    96. // 获取队列前端元素
    97. public int getFirst() {
    98. if (isEmpty()) {
    99. throw new IllegalStateException("队列为空");
    100. }
    101. return front.data;
    102. }
    103. // 获取队列尾部元素
    104. public int getLast() {
    105. if (isEmpty()) {
    106. throw new IllegalStateException("队列为空");
    107. }
    108. return rear.data;
    109. }
    110. // 判断队列是否为空
    111. public boolean isEmpty() {
    112. return size == 0;
    113. }
    114. // 获取队列大小
    115. public int size() {
    116. return size;
    117. }
    118. }

  • 相关阅读:
    pat乙级1120(买地攻略) C++
    华为云云耀云服务器L实例评测|基于L实例安装Prometheus+Grafana插件实现数据可视化监控
    15 -python之文件操作
    Latex伪代码中函数的写法
    RabbitMQ的常见工作模式
    [附源码]计算机毕业设计springboot创意摄影交流平台
    node.js学习之路由、中间件
    webpack 优化方式
    Vue中使用高德地图
    TCP协议详解
  • 原文地址:https://blog.csdn.net/Mar_mxs/article/details/137967110