题目:

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

The cache is initialized with a positive capacity.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4

分析:

设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

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

按照所给的例子看一下cache内部是如何变化的。

  front back result
put(1, 1) (1, 1)    
put(2, 2) (2, 2) (1, 1)  
get(1) (1, 1) (2, 2) 1
put(3, 3) (3, 3) (1, 1)  
get(2) (3, 3) (1, 1) -1
put(4, 4) (4, 4) (3, 3)  
get(1) (4, 4) (3, 3) -1
get(3) (3, 3) (4, 4) 3
get(4) (4, 4) (3, 3) 4

很清楚的就理解了LRU的机制,当get的key在cache中已经存在时,就将存储的内容放到最前面,get的key不存在时就返回-1。

put的新的key-value时,如果达到了容量上限,就删除一个最近最少使用的,实际上也是队尾的元素,然后将新的key-value存储到最前面。

因为我们每次要O(1)的复杂度,所以可以使用hashmap来get数据,而当容量达到上限时,要删除最近最少使用的,且要在最前面put进新的数据,要使用一个双向链表,来保证O(1)的时间复杂度。

java中可以使用LinkeHashMap来实现LRU缓存。

程序:

C++

class LRUCache {
public:
LRUCache(int capacity) {
cap = capacity;
} int get(int key) {
auto it = map.find(key);
if(it == map.end())
return -1;
l.splice(l.begin(), l, it->second);
return it->second->second;
} void put(int key, int value) {
auto it = map.find(key);
if(it != map.end()){
l.erase(it->second);
}
l.push_front(make_pair(key, value));
map[key] = l.begin();
if (map.size() > cap) {
int k = l.rbegin()->first;
l.pop_back();
map.erase(k);
}
}
private:
int cap;
list<pair<int, int>> l;
unordered_map<int, list<pair<int, int>>::iterator> map;
};

Java

class LRUCache {

    public LRUCache(int capacity) {
this.cap = capacity;
this.map = new HashMap<>();
this.dummyHead = new Node(0, 0);
this.tail = new Node(0, 0); dummyHead.prev = null;
dummyHead.next = tail;
tail.prev = dummyHead;
tail.next = null;
} public int get(int key) {
if(!map.containsKey(key))
return -1;
Node node = map.get(key);
removeNode(node);
addToHead(node);
return node.val;
} public void put(int key, int value) {
if(map.containsKey(key)){
Node node = map.get(key);
removeNode(node);
map.remove(key);
size--;
}
Node node = new Node(key, value);
map.put(key, node);
if(size < cap){
addToHead(node);
size++;
}else {
map.remove(tail.prev.key);
removeNode(tail.prev);
addToHead(node);
}
} private void removeNode(Node node){
node.prev.next = node.next;
node.next.prev = node.prev;
} private void addToHead(Node node){
node.next = dummyHead.next;
node.next.prev = node;
dummyHead.next = node;
node.prev = dummyHead;
} class Node{
int key;
int val;
Node prev;
Node next;
public Node(int key, int val){
this.key = key;
this.val = val;
}
}
private int cap;
private Map<Integer, Node> map;
private Node dummyHead;
private Node tail;
private int size;
}
class LRUCache {

    public LRUCache(int capacity) {
this.capacity = capacity;
map = new LinkedHashMap<>();
} public int get(int key) {
if(map.containsKey(key)) {
int value = map.get(key);
map.remove(key);
map.put(key, value);
return value;
}
return -1;
} public void put(int key, int value) {
if(map.containsKey(key)) {
map.remove(key);
}
map.put(key, value);
if(map.size() > capacity) {
map.remove(map.keySet().iterator().next());
}
}
private int capacity;
private LinkedHashMap<Integer, Integer> map;
}

LeetCode 146. LRU CacheLRU缓存机制 (C++/Java)的更多相关文章

  1. [leetcode]146. LRU CacheLRU缓存

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  2. 重学数据结构(三)——使用单链表实现LRU淘汰缓存机制

    使用单链表实现LRU(Least Recently Used)淘汰缓存机制 需求:存在一个单链表,在单链表尾部的都是越早之前添加的元素. 当元素被访问到时,会添加进缓存(也就是这个单链表中). 如果这 ...

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

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

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

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

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

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

  6. Leetcode 146. LRU 缓存机制

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

  7. 如何利用缓存机制实现JAVA类反射性能提升30倍

    一次性能提高30倍的JAVA类反射性能优化实践 文章来源:宜信技术学院 & 宜信支付结算团队技术分享第4期-支付结算部支付研发团队高级工程师陶红<JAVA类反射技术&优化> ...

  8. leetcode 146. LRU Cache 、460. LFU Cache

    LRU算法是首先淘汰最长时间未被使用的页面,而LFU是先淘汰一定时间内被访问次数最少的页面,如果存在使用频度相同的多个项目,则移除最近最少使用(Least Recently Used)的项目. LFU ...

  9. [LeetCode] 146. LRU Cache 最近最少使用页面置换缓存器

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  10. [LeetCode] 146. LRU Cache 近期最少使用缓存

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

随机推荐

  1. 【c++】类valarray介绍

    valarray类用于处理数组中的数值,如将所有元素相加,找出最大.最小值,数组长度. 如何使用valarray类: 1.首先需要声明头文件        #include<valarray&g ...

  2. 用百度和神策做埋点为何pv差异很大?

    近期ClkLog收到一个客户反馈说我们与百度统计的PV数据差异很大.为了验证问题,开发进行了一次对页面浏览量统计的测试.针对同一个IP同一个时间的页面浏览量统计发现,百度的统计数据只有一条,而ClkL ...

  3. 深度解读《深度探索C++对象模型》之C++虚函数实现分析(一)

    接下来我将持续更新"深度解读<深度探索C++对象模型>"系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,自动获得推文和全部的文章列表. 假如有这样的一段 ...

  4. 璀璨智行:V2X车路协同智慧交通

    ​V2X车用无线通信技术是指车对外界的信息交换,作为未来智能交通运输系统的关键技术,璀璨智行潜心研究V2X技术,致力于V2X车路协同的落地,在智慧交通领域做出了卓越的贡献. 创业机会点 魏军博表示:& ...

  5. PolarDB 并行查询的前世今生

    简介:本文会深入介绍PolarDB MySQL在并行查询这一企业级查询加速特性上做的技术探索.形态演进和相关组件的实现原理,所涉及功能随PolarDB MySQL 8.0.2版本上线. ​ 作者 | ...

  6. WPF 由于系统颜色配置 Mscms 组件损坏启动失败

    本文记录 WPF 应用程序,因为系统的颜色配置 Mscms.dll 组件损坏导致应用加载图片失败,从而启动失败的原因和解决方法 在 WPF 应用加载图片时,将会调用到系统的 Mscms.dll 组件. ...

  7. 提示工程(Prompt Engineering)将ChatGPT调教为傲娇猫娘~喵

    Prompt Engineering(提示工程)是指通过设计精心构造的提示(prompt)或者输入,来引导大型语言模型生成特定类型的输出.这个技术背后的原理是利用模型对输入的敏感性,通过提供特定格式或 ...

  8. k3s安装---适配边缘计算场景的轻量级的k8s(二)

    三.安装k8s k3s官网:https://k3s.io 文档: github:https://github.com/k3s-io/k3s 3.1 安装基础环境 # 安装基础环境 1.安装yum源 c ...

  9. RVM Ruby 版本管理器的删除 Gatling

    参考: https://www.jianshu.com/p/aef65d0c03a4

  10. SpringBoot连接redis报错:exception is io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接

    一.解决思路 (1).检查redis的配置是否正确 spring redis: host: localhost port: 6379 password: 123456 database: 0 time ...