LRU先进先出算法
//双链表节点
struct dListNode{ dListNode* pre; dListNode* next; int key; int value; dListNode(int k = 0, int v = 0) :key(k), value(v), pre(NULL), next(NULL){} }; class LRUCache { public: LRUCache(int capacity):_size(capacity) { head = new dListNode(); tail = new dListNode(); head->next = tail; tail->pre = head; } void removeNode(dListNode* node) { node->pre->next = node->next; node->next->pre = node->pre; //delete node; } void aJustNodeToHead(dListNode* newNode) { //新节点头插 head->next->pre = newNode; newNode->next = head->next; head->next = newNode; newNode->pre = head; //map关联到链表 //_map.insert(make_pair(key, newNode)); } int get(int key) { auto iter = _map.find(key); if (iter != _map.end()) { //存在,先删除再头插 dListNode* node = iter->second; int targetNum = node->value; //_map.erase(key); removeNode(node); aJustNodeToHead(node); return targetNum; } return -1; } void put(int key, int value) { auto iter = _map.find(key); if (iter != _map.end()) { //存在,先删除再头插 dListNode* node = iter->second; //值变化 node->value = value; removeNode(node); aJustNodeToHead(node); } else { //不存在 if (_map.size() == _size) { //满了得先删除尾部,再头插 _map.erase(tail->pre->key); auto iter = tail->pre; removeNode(tail->pre); delete iter; } dListNode* newNode = new dListNode(key, value); aJustNodeToHead(newNode); _map.insert(make_pair(key, newNode)); } } private: dListNode* head; dListNode* tail; unordered_map<int, dListNode*> _map; int _size; };
leetcode上的题目,使用最优的时间复杂度,用hashmap保存指向双链表的指针实现查找O(1),而双链表的删除也是O(1),put和get元素都是O(1),hashmap+双链表的方法真的神,一开始自己用vector和list虽然也实现了功能,但是数据就惨很多,原因是list的查找是O(n)的,还需要定义一个指定大小的vector,着实扣脚,下边给出这个版本供参考:
class LRUCache { public: LRUCache(int capacity):_size(capacity) { //扩容到足够大 _vec.resize(3001); } int get(int key) { if(_vec[key]==0)return -1; int target =-1; for(auto iter=_list.begin();iter!=_list.end();++iter) { if(iter->first==key) { target=iter->second; _list.erase(iter); _list.push_back(make_pair(key,target)); break; } } return target; } void put(int key, int value) { //存在先删除 if(_vec[key]>0) { for(auto iter = _list.begin();iter!=_list.end();++iter) { if(iter->first==key) { _list.erase(iter); break; } } } if(_list.size()==_size) { //满了,说明不存在,直接删除头 auto top=_list.front(); --_vec[top.first]; _list.pop_front(); } _list.push_back(pair<int,int>(key,value)); ++_vec[key]; } private: list<pair<int,int>> _list; //记录每个key是否存在 vector<int> _vec; //链表最大长度 int _size; };
纯属记录程序人生,如有差错,欢迎指正,轻喷
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通