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
cpp 复制代码
class LRUCache {
public:
	LRUCache(int capacity) {
		m_capacity = capacity;
	}

	int get(int key) {
		if (!key2node.count(key))  return -1;
		//将cache中从key2node[key]开始指导cache末尾的元素移动到cache.begin前
		cache.splice(cache.begin(), cache, key2node[key]);
		return key2node[key]->second;
	}

	void put(int key, int value) {
		//存在,则擦除实际存储元素
		if (key2node.count(key)) cache.erase(key2node[key]);
		//检查当前是否达到的最大容量,如果是,则擦除最近最少使用的尾部元素,同时清除存储的元素
		if (cache.size()==m_capacity){
			key2node.erase(cache.back().first);
			cache.pop_back();
		}
		//插入元素
		cache.push_front({ key,value });
		//更新最近使用的元素
		key2node[key] = cache.begin();
	}
private:
	int m_capacity;
	//key2node哈希表,key映射一个迭代器,指向cache中{ key,value }
	unordered_map<int, list<pair<int ,int>>::iterator> key2node;
	//cache双向链表,保存{ key,value }
	list<pair<int, int>> cache;
};
相关推荐
青山木19 分钟前
Hot 100 --- 跳跃游戏 II
java·数据结构·算法·leetcode·贪心算法
Tisfy22 分钟前
LeetCode 3870.统计范围内的逗号:模拟 或 一步计算
数学·算法·leetcode·题解·模拟·遍历
明月_清风32 分钟前
字符串匹配四大经典算法:BF、RK、BM、KMP 到底有什么区别?
后端·算法
极小狐32 分钟前
CI 流水线提速实战:缓存设计与依赖代理的工程实践
缓存·ci/cd·gitlab·devops
程序喵大人34 分钟前
【C++入门】值类别与表达式 - 03 引用绑定:为什么有些参数能接住临时对象
开发语言·c++·引用绑定
明月_清风1 小时前
多模式字符串匹配:Trie 与 AC 自动机
后端·算法
莫得感情 o1 小时前
Redis 09 · 高可用:Sentinel 如何发现故障并完成切主
redis·缓存·sentinel
木井巳1 小时前
【BFS/DFS 解决 FloodFill 算法】衣橱整理
java·算法·leetcode·深度优先·广度优先·宽度优先
热心网友俣先生1 小时前
2026年高教社杯数模国赛A题:五年命题规律与预测
算法·机器学习·数学建模
handler011 小时前
【Linux】信号:内核的“敲门声”
linux·运维·服务器·c++·c·信号·signal