题目

146. LRU缓存机制

思路

  • 利用双链表和HashMap来解题
  • 看到链表题目,我们可以使用头尾结点可以更好进行链表操作和边界判断等
  • 还需要使用size变量来存储双链表的当前长度
  • 调用get,如果存在的话,我们可以调用将在双链表中的结点通过修改指针移动到第一个;如果调用put,我们先判断是否存在该结点,如果不存在,可直接将链接插入即可,同时size++,如果存在的话,先删除原来的结点,再将新结点push到头部即可

代码

  1. class LRUCache {
  2. class Node {
  3. int key;
  4. int val;
  5. Node pre;
  6. Node next;
  7. public Node() {}
  8. public Node(int key, int val) {
  9. this.key = key;
  10. this.val = val;
  11. }
  12. }
  13. // 哈希表中的node和双链表的node是同一个结点
  14. private HashMap<Integer, Node> cache;
  15. private Node dummyHead;
  16. private Node dummyTail;
  17. private int size;
  18. private int capacity;
  19. public LRUCache(int capacity) {
  20. cache = new HashMap<>();
  21. dummyHead = new Node();
  22. dummyTail = new Node();
  23. dummyHead.next = dummyTail;
  24. dummyTail.pre = dummyHead;
  25. this.capacity = capacity;
  26. this.size = 0;
  27. }
  28. public int get(int key) {
  29. // 先获取看看结点存不存在
  30. Node node = cache.get(key);
  31. // 如果存在的话,将当前访问的结点移动到链表头,并且返回值
  32. if (node != null) {
  33. moveToHead(node);
  34. return node.val;
  35. }
  36. // 不存在的话就返回-1
  37. return -1;
  38. }
  39. public void put(int key, int value) {
  40. // 也是先看看结点是否存在
  41. Node node = cache.get(key);
  42. // 如果存在,那么要做的操作就是将结点移动到链表头,然后更新结点值即可
  43. if (node != null) {
  44. node.val = value;
  45. moveToHead(node);
  46. } else {
  47. // 如果不存在的话我们就要创建新结点插入
  48. Node newNode = new Node(key, value);
  49. // 先添加到哈希表中
  50. cache.put(key, newNode);
  51. // 再添加到链表中
  52. addToHead(newNode);
  53. // 并且长度+1
  54. size++;
  55. // 因为我们设定最大容量,我们还要判断新put的结点后,容量是否超过了capacity,超过了话,删除最后一个结点,并且长度-1
  56. if (size > capacity) {
  57. Node tail = removeTail();
  58. cache.remove(tail.key);
  59. size--;
  60. }
  61. }
  62. }
  63. /**
  64. * 将node移动到最前面
  65. */
  66. private void moveToHead(Node node) {
  67. if (size > 0 && size <= capacity) {
  68. remove(node);
  69. addToHead(node);
  70. }
  71. }
  72. /**
  73. * 删除node结点
  74. */
  75. private void remove(Node node) {
  76. if (size > 0) {
  77. node.pre.next = node.next;
  78. node.next.pre = node.pre;
  79. }
  80. }
  81. /**
  82. * 删除最后一个结点
  83. */
  84. private Node removeTail() {
  85. if (size > 0) {
  86. Node node = dummyTail.pre;
  87. remove(node);
  88. return node;
  89. }
  90. return null;
  91. }
  92. /**
  93. * 添加新结点到第一位去
  94. */
  95. private void addToHead(Node node) {
  96. node.next = dummyHead.next;
  97. dummyHead.next = node;
  98. node.next.pre = node;
  99. node.pre = dummyHead;
  100. }
  101. }

复杂度分析

  • 时间复杂度:\(O(1)\)
  • 空间复杂度:\(O(N)\),其中 N 为初始化的 capacity 容量

力扣 - 146. LRU缓存机制的更多相关文章

  1. 【golang必备算法】 Letecode 146. LRU 缓存机制

    力扣链接:146. LRU 缓存机制 思路:哈希表 + 双向链表 为什么必须要用双向链表? 因为我们需要删除操作.删除一个节点不光要得到该节点本身的指针,也需要操作其前驱节点的指针,而双向链表才能支持 ...

  2. Java实现 LeetCode 146 LRU缓存机制

    146. LRU缓存机制 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - ...

  3. 146. LRU 缓存机制 + 哈希表 + 自定义双向链表

    146. LRU 缓存机制 LeetCode-146 题目描述 题解分析 java代码 package com.walegarrett.interview; /** * @Author WaleGar ...

  4. 【力扣】146. LRU缓存机制

    运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果关键字 (key) ...

  5. [Leetcode]146.LRU缓存机制

    Leetcode难题,题目为: 运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key ...

  6. 146. LRU缓存机制

    题目描述 运用你所掌握的数据结构,设计和实现一个LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (key ...

  7. leetcode:146. LRU缓存机制

    题目描述: 运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 ( ...

  8. LeetCode 146. LRU缓存机制(LRU Cache)

    题目描述 运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (k ...

  9. Leetcode 146. LRU 缓存机制

    前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓存,而且在内存和硬盘有内存缓存.当主存容量远大于CPU缓存,或磁盘容量远大于主存时,哪 ...

随机推荐

  1. 满屏的try-catch,不瘆得慌?

    持续原创输出,点击上方蓝字关注我 目录 前言 Spring Boot 版本 全局统一异常处理的前世今生 Spring Boot的异常如何分类? 如何统一异常处理? 异常匹配的顺序是什么? 总结 前言 ...

  2. 小白使用Hystrix

    Hystrix是什么东西?百度一下: 没错,hystrix是豪猪的意思,作为SpringCloud微服务系统中保持服务稳定的重要组件,正如它的名字一样,它对整个系统起到了保护的作用. 在许多文章当中把 ...

  3. 利用 yum 命令和 rpm 命令升级 Nginx 或者安装最新版本 Nginx

    方法一:使用 yum 命令升级 Nginx 1.在配置 YUM 仓库的目录(/etc/yum.repos.d/)下新增文件  nginx.repo vi /etc/yum.repos.d/nginx. ...

  4. spring cloud 实现基于Nacos权重的负载均衡

    package com.water.step.service.user.nacos; import com.alibaba.nacos.api.exception.NacosException; im ...

  5. 多测师讲解selenium_iframe框定位_高级讲师肖sir

    iframe 框定位方法: 查看iframe框 京东点击登录定位元素 定位qq: qq登录定位的元素 查找iframe框 定位iframe框 from selenium import webdrive ...

  6. linq 整理(前序)

    前言 对linq进行整理,分为前序.中序和后序. 前序就是一些简单的概念和模拟. 中序的话就是深挖一些思想. 后序对其进行解刨. 正文 语言集成查询 (LINQ) 是一系列直接将查询功能集成到 C# ...

  7. MeteoInfoLab脚本示例:AIRS Swath HDF数据

    例子中的AIRS Swath HDF数据在Polar Stereographic(南极)投影中接近矩形,需要先从数据中读出经纬度及相关数据数组,利用surfacem函数绘制Swath数据(散点),在s ...

  8. docker 启动redis/nginx

    1.docker 启动redis   # redis docker run -itd --name redis-test -p 16379:6379 redis   2.docker 启动nginx ...

  9. zookeeper 集群搭建 转

    通过 VMware ,我们安装了三台虚拟机,用来搭建 zookeeper 集群,虚拟机网络地址如下: hostname                      ipaddress           ...

  10. rabbitmq 延时队列 插件方式实现 每条消息都延时自己时间

    上篇文章的延时是加到队列上的 通过死信过时推送 ,缺点就是不能每条消息定义自己的过时时间而且每次有新的过时时间,要新建一个交换机和队列 https://www.cnblogs.com/brady-wa ...