• LeetCode--代码详解 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
    

    提示:

    • 1 <= capacity <= 3000
    • 0 <= key <= 10000
    • 0 <= value <= 105
    • 最多调用 2 * 105 次 get 和 put

    思路

    哈希表+双向链表

    本题可以使用java中封装好的LinkedHashMap

    这里用手写链表的形式

    map的key存储key,value存储链表节点

    代码

    1. class LRUCache {
    2. class LinkedNode{
    3. LinkedNode prev,next;
    4. int key,value;
    5. public LinkedNode(int key, int value){
    6. this.key = key;
    7. this.value = value;
    8. }
    9. }
    10. HashMap map;
    11. LinkedNode head,tail; //头尾指针
    12. int size,capacity; //当前容量、总容量
    13. //构造函数,初始化
    14. public LRUCache(int capacity) {
    15. map = new HashMap<>();
    16. this.capacity=capacity;
    17. head = new LinkedNode(-1,-1);
    18. tail = new LinkedNode(-1,-1);
    19. head.next = tail;
    20. tail.prev = head;
    21. size = 0;
    22. }
    23. public int get(int key) {
    24. if(map.containsKey(key)){
    25. LinkedNode node = map.get(key);
    26. if(tail.prev != node){
    27. deleteNode(node);
    28. addNodeToLast(node);
    29. }
    30. return node.value;
    31. }
    32. return -1;
    33. }
    34. public void put(int key, int value) {
    35. if(map.containsKey(key)){
    36. LinkedNode node = map.get(key);
    37. node.value=value;
    38. deleteNode(node);
    39. }else{
    40. if(size < capacity){ //还有容量,直接添加
    41. size++;
    42. }else{
    43. map.remove(head.next.key);
    44. deleteNode(head.next);
    45. }
    46. }
    47. LinkedNode newNode = new LinkedNode(key,value);
    48. addNodeToLast(newNode);
    49. map.put(key,newNode);
    50. }
    51. //删除
    52. private void deleteNode(LinkedNode node){
    53. node.prev.next=node.next;
    54. node.next.prev=node.prev;
    55. }
    56. //添加到最后一个
    57. private void addNodeToLast(LinkedNode node){
    58. node.prev = tail.prev;
    59. node.prev.next=node;
    60. node.next = tail;
    61. tail.prev=node;
    62. }
    63. }
    64. /**
    65. * Your LRUCache object will be instantiated and called as such:
    66. * LRUCache obj = new LRUCache(capacity);
    67. * int param_1 = obj.get(key);
    68. * obj.put(key,value);
    69. */

  • 相关阅读:
    简易版 vue实现
    核心实验13合集_vlan mapping 和QinQ_ENSP
    软件测试工程师的职场发展顺序,月薪30k的测试岗技术要求是真的高...
    评论列表案例,通过Ajax向服务器发送请求
    【实用工具】frp实现内网穿透
    YOLOv7如何提高目标检测的速度和精度,基于模型结构、数据增强提高目标检测速度
    代码静态检查实践
    【Linux】Linux 编译器与调试器 -- gcc/g++/gdb 的使用
    了解什么是架构基本概念和架构本质
    使用Jmeter+ant进行接口自动化测试(数据驱动)
  • 原文地址:https://blog.csdn.net/hcjdhsjs/article/details/136492743