题目:

设计和构建一个“最近最少使用”缓存,该缓存会删除最近最少使用的项目。缓存应该从键映射到值(允许你插入和检索特定键对应的值),并在初始化时指定最大容量。当缓存被填满时,它应该删除最近最少使用的项目。

它应该支持以下操作: 获取数据 get 和 写入数据 put 。

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得密钥 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得密钥 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4

有问题的:

    class LRUCache {LinkedHashMap<Integer,Integer> map;int capacity;public LRUCache(int capacity) {map = new LinkedHashMap<Integer,Integer>(capacity, 0.75f,true);this.capacity = capacity;}public int get(int key) {if (map.containsKey(key)){return map.get(key);}return -1;}public void put(int key, int value) {if (map.size() == capacity) {Set<Map.Entry<Integer, Integer>> entries = map.entrySet();Iterator<Map.Entry<Integer, Integer>> iterator = entries.iterator();Map.Entry<Integer, Integer> next = null;if (iterator.hasNext()) {next = iterator.next();}if (next != null) {map.remove(next.getKey());}}map.put(key,value);}}

发现自己的put 没有去检索当前map 里面是不是包含同样的key,这样的话,就不需要remove 掉一个元素。第二,发现自己对removeEldestEntry 方法不熟悉。

正确解决方法一:(偷懒)

class LRUCache extends LinkedHashMap<Integer, Integer>{private int capacity;public LRUCache(int capacity) {super(capacity, 0.75F, true);this.capacity = capacity;}public int get(int key) {return super.getOrDefault(key, -1);}public void put(int key, int value) {super.put(key, value);}@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {return size() > capacity; }
}

方法二:

    class LRUCache {class Node{public Node pre;public Node nex;public int value;public Node(int value){this.value = value;}}//Map map ;Node head,tail;int capacity;public LRUCache(int capacity) {map = new HashMap(capacity);head = new Node(-1);tail = new Node(-1);head.nex = tail;tail.pre = head;this.capacity = capacity;}public int get(int key) {// haveif (map.containsKey(key)) {// find keyNode node = findKey(key);//move to headmoveToFirst(node);//get valuereturn (int) map.get(key);}else {// not contains return -1return -1;}}public void put(int key, int value) {if (map.containsKey(key)) {//findNode node = findKey(key);// to headmoveToFirst(node);map.put(key,value);}else {if (map.size() > capacity) {//remove lastNode pre = tail.pre;Node node = pre.pre;node.nex = tail;tail.pre = node;// put newputNew(key, value);map.remove(pre.value);}else {putNew(key, value);}}}private void putNew(int key, int value) {// put newNode node = new Node(key);map.put(key, value);//move to headmoveToFirst(node);}public Node findKey(int key){// find keyNode cur = head.nex;//LinkedHashMap 也这样查找吗?while (cur != null) {if (cur.value == key) {return cur;}cur = cur.nex;}return null;}public void moveToFirst(Node node){//if  is headif (head.nex == node) {return;}// 衔接nodeif (node.pre != null){Node pre1 = node.pre;Node nex1 = node.nex;pre1.nex = nex1;nex1.pre = pre1;}Node pre = head.nex;head.nex = node;node.pre = head;node.nex = pre;pre.pre = node;}}

有点乱 写了一个小时才写出来
不好的地方在于 hasMap 的value 应该放Node
这样就不需要findKey

建议参考:

public class LRUCache {class DLinkedNode {int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int _key, int _value) {key = _key; value = _value;}}private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();private int size;private int capacity;private DLinkedNode head, tail;public LRUCache(int capacity) {this.size = 0;this.capacity = capacity;// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}public int get(int key) {DLinkedNode node = cache.get(key);if (node == null) {return -1;}// 如果 key 存在,先通过哈希表定位,再移到头部moveToHead(node);return node.value;}public void put(int key, int value) {DLinkedNode node = cache.get(key);if (node == null) {// 如果 key 不存在,创建一个新的节点DLinkedNode newNode = new DLinkedNode(key, value);// 添加进哈希表cache.put(key, newNode);// 添加至双向链表的头部addToHead(newNode);++size;if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode tail = removeTail();// 删除哈希表中对应的项cache.remove(tail.key);--size;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部node.value = value;moveToHead(node);}}private void addToHead(DLinkedNode node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(DLinkedNode node) {node.prev.next = node.next;node.next.prev = node.prev;}private void moveToHead(DLinkedNode node) {removeNode(node);addToHead(node);}private DLinkedNode removeTail() {DLinkedNode res = tail.prev;removeNode(res);return res;}
}

思考:

1.写算法应该先写逻辑
// fink key
//return value
//…
保证每一步骤都不能少
比如此题
如果超过了容量
要从map里面remove 掉
不然就会有问题

2.写的每一行代码 写完要思考一下对不对
比如 >= 写成了> 结果可能就错了
你在每一行都思考一下
出了错误页不需要整个篇幅去排查问题了

算法---Lru缓存(Java)相关推荐

  1. 数据结构与算法 / LRU 缓存淘汰算法

    一.诞生原因 缓存是一种提供数据读取性能的技术,在硬件设计.软件开发中有广泛的应用,比如常见的 CPU 缓存,DB 缓存和浏览器缓存等.但是缓存的大小是有限的,需要一定的机制判断哪些数据需要淘汰,即: ...

  2. 高级数据结构与算法 | LRU缓存机制(Least Recently Used)

    文章目录 LRUCache的原理 LRUCache的实现 LRUCache的原理 LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法. 什么是 Cac ...

  3. 【文科生带你读JavaScript数据结构与算法】2. 双向链表与LRU缓存算法原理与实现(下)

    上篇聊了聊双向链表(doubly linked list)这个数据结构,今天就来点更实际的,也可以用双链表来实现的一种生活工作中不可或缺的优化算法--LRU缓存(Least Recently Used ...

  4. 高级数据结构与算法 | LFU缓存机制(Least Frequently Used)

    文章目录 LFUCache 结构设计 LFUCache的实现 在之前我写过一篇LRU的博客,如果不了解的建议先看看这篇 高级数据结构与算法 | LRU缓存机制(Least Recently Used) ...

  5. java 最少使用(lru)置换算法_缓存置换算法 - LRU算法

    LRU算法 1 原理 对于在内存中并且不被使用的数据块就是LRU,这类数据需要从内存中删除,以腾出空间来存储常用的数据. LRU算法(Least Recently Used,最近最少使用),是内存管理 ...

  6. 看动画轻松理解「链表」实现「LRU缓存淘汰算法」

    作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...

  7. LRU缓存实现(Java)

    LRU是Least Recently Used 的缩写,翻译过来就是"最近最少使用",LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的 ...

  8. LinkedHashMap实现LRU缓存算法

    缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的. LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉. 先说说List:每次访问一个 ...

  9. 06 | 链表(上):如何实现LRU缓存淘汰算法?

    缓存 作用 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存.数据库缓存.浏览器缓存等等. 淘汰策略 常见的策略有三种:先进先出策略 FIFO(F ...

最新文章

  1. 字节跳动AI Lab社招以及实习生内推
  2. 个人知识管理系统 mysql_个人知识管理系统Version1.0开发记录(04)
  3. Win7下U盘安装Ubuntu14.04双系统
  4. 十七、Pytorch的安装和使用
  5. Extjs不错的博客
  6. Asp.Net Session 丢失的奇怪问题,求救!
  7. linux 跨服务器备份,用BackupPC架设Linux跨平台备份服务器
  8. Python字符串常用方法(split,partition,maketrans,strip...)
  9. ubuntu 12.04安装vncserver
  10. 运动目标跟踪(三)--搜索算法优化搜索方向之Meanshift
  11. 布隆过滤器(Bloom Filter)详解
  12. 解决在ubuntu环境下, sublime不能输入中文的问题
  13. Axure RP8下载以及注册
  14. 关于DTC诊断故障码的获取与清除(ISO14229系列之14、19服务)
  15. vc707(virtex7)FLASH下载实验
  16. 微信商户号转账到个人银行卡加密算法及结果查询问题
  17. Git 图标无法正常显示解决方案
  18. 运维堡垒机—如何解决企业运维操作审计问题?
  19. python如何把csv转化为xls_python中如何将csv文件转为xls文件
  20. NTFS -usnjournal监控

热门文章

  1. html获取文本框的值,如何获取输入框的内容
  2. arduino项目_quot;Arduino智能车项目quot;实战班开班!
  3. C++知识点46——类继承中的类型转换与访问权限控制(中)
  4. 字符串排序 java_java字符串排序
  5. Kubernetes(1) kubectl 入门
  6. MongoDB用户授权和管理
  7. Effective_STL 学习笔记(二十八) 了解如何通过 reverse_iterator 的 base 得到 iterator...
  8. Cisco路由交换--NAT详解一
  9. iPhoneX延迟这么久预订,真实原因连库克也没料到
  10. Ubuntu架设FTP