算法---Lru缓存(Java)
题目:
设计和构建一个“最近最少使用”缓存,该缓存会删除最近最少使用的项目。缓存应该从键映射到值(允许你插入和检索特定键对应的值),并在初始化时指定最大容量。当缓存被填满时,它应该删除最近最少使用的项目。
它应该支持以下操作: 获取数据 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)相关推荐
- 数据结构与算法 / LRU 缓存淘汰算法
一.诞生原因 缓存是一种提供数据读取性能的技术,在硬件设计.软件开发中有广泛的应用,比如常见的 CPU 缓存,DB 缓存和浏览器缓存等.但是缓存的大小是有限的,需要一定的机制判断哪些数据需要淘汰,即: ...
- 高级数据结构与算法 | LRU缓存机制(Least Recently Used)
文章目录 LRUCache的原理 LRUCache的实现 LRUCache的原理 LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法. 什么是 Cac ...
- 【文科生带你读JavaScript数据结构与算法】2. 双向链表与LRU缓存算法原理与实现(下)
上篇聊了聊双向链表(doubly linked list)这个数据结构,今天就来点更实际的,也可以用双链表来实现的一种生活工作中不可或缺的优化算法--LRU缓存(Least Recently Used ...
- 高级数据结构与算法 | LFU缓存机制(Least Frequently Used)
文章目录 LFUCache 结构设计 LFUCache的实现 在之前我写过一篇LRU的博客,如果不了解的建议先看看这篇 高级数据结构与算法 | LRU缓存机制(Least Recently Used) ...
- java 最少使用(lru)置换算法_缓存置换算法 - LRU算法
LRU算法 1 原理 对于在内存中并且不被使用的数据块就是LRU,这类数据需要从内存中删除,以腾出空间来存储常用的数据. LRU算法(Least Recently Used,最近最少使用),是内存管理 ...
- 看动画轻松理解「链表」实现「LRU缓存淘汰算法」
作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...
- LRU缓存实现(Java)
LRU是Least Recently Used 的缩写,翻译过来就是"最近最少使用",LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的 ...
- LinkedHashMap实现LRU缓存算法
缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的. LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉. 先说说List:每次访问一个 ...
- 06 | 链表(上):如何实现LRU缓存淘汰算法?
缓存 作用 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存.数据库缓存.浏览器缓存等等. 淘汰策略 常见的策略有三种:先进先出策略 FIFO(F ...
最新文章
- 字节跳动AI Lab社招以及实习生内推
- 个人知识管理系统 mysql_个人知识管理系统Version1.0开发记录(04)
- Win7下U盘安装Ubuntu14.04双系统
- 十七、Pytorch的安装和使用
- Extjs不错的博客
- Asp.Net Session 丢失的奇怪问题,求救!
- linux 跨服务器备份,用BackupPC架设Linux跨平台备份服务器
- Python字符串常用方法(split,partition,maketrans,strip...)
- ubuntu 12.04安装vncserver
- 运动目标跟踪(三)--搜索算法优化搜索方向之Meanshift
- 布隆过滤器(Bloom Filter)详解
- 解决在ubuntu环境下, sublime不能输入中文的问题
- Axure RP8下载以及注册
- 关于DTC诊断故障码的获取与清除(ISO14229系列之14、19服务)
- vc707(virtex7)FLASH下载实验
- 微信商户号转账到个人银行卡加密算法及结果查询问题
- Git 图标无法正常显示解决方案
- 运维堡垒机—如何解决企业运维操作审计问题?
- python如何把csv转化为xls_python中如何将csv文件转为xls文件
- NTFS -usnjournal监控
热门文章
- html获取文本框的值,如何获取输入框的内容
- arduino项目_quot;Arduino智能车项目quot;实战班开班!
- C++知识点46——类继承中的类型转换与访问权限控制(中)
- 字符串排序 java_java字符串排序
- Kubernetes(1) kubectl 入门
- MongoDB用户授权和管理
- Effective_STL 学习笔记(二十八) 了解如何通过 reverse_iterator 的 base 得到 iterator...
- Cisco路由交换--NAT详解一
- iPhoneX延迟这么久预订,真实原因连库克也没料到
- Ubuntu架设FTP