页面置换算法LRU实现--leetcode O(1)时间复杂度
来源:互联网 发布:杀破狼js 编辑:程序博客网 时间:2024/05/22 04:34
转载
作者:鱼与海洋
出处:http://www.cnblogs.com/joannacode/p/5998949.html
leetcode题目地址
https://leetcode.com/problems/lru-cache/
题目描述
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.
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 1cache.put(3, 3); // evicts key 2cache.get(2); // returns -1 (not found)cache.put(4, 4); // evicts key 1cache.get(1); // returns -1 (not found)cache.get(3); // returns 3cache.get(4); // returns 4
Subscribe to see which companies asked this question.
ac代码
采用 双向链表 + map(效率还是不错的 map进一步可用成unordered_map)
- 数据结构设计
typedef struct node{ int key; int val; struct node* pre; struct node* next; node(int _key = -1, int _val = -1) { key = _key; val = _val; pre = NULL; next = NULL; }}DNode;class LRUCache{public: LRUCache(int _capacity) { capacity = _capacity; size = 0; head = new DNode(); tail = new DNode(); head->next = tail; tail->pre = head; mp.clear(); } int get(int key) { map<int,DNode*>::iterator it= mp.find(key); if(it == mp.end()) //如果在Cache中不存在该key, 则返回-1 { return -1; } else { DNode* t = it->second; // 把 t分离出来,然后将t插入到头部位置 t->pre->next = t->next; t->next->pre = t->pre; t->pre = head; t->next = head->next; head->next = t; t->next->pre = t; return t->val; } } void put(int key, int value) { map<int,DNode*>::iterator it= mp.find(key); if(it == mp.end()) //如果在Cache中不存在该key, 则返回-1 { if(size == capacity) //如果双向链表容量已满即缓存容量已满,则将最近不使用的节点即链表最后一个数据节点删除 { // 删除最后一个 DNode *tmp = tail->pre; tail->pre->pre->next = tail; tail->pre = tmp->pre; mp.erase(tmp->key); delete tmp; size--; } //把新节点插入到head的后面 更新map DNode *newNode = new DNode(key, value); newNode->pre = head; newNode->next = head->next; head->next = newNode; newNode->next->pre = newNode; mp[key] = newNode;//在hashtable添加key对应的表项 size++;//链表节点数++ }else{ // 当前put的可以存在,需要更新value DNode* t = it->second; // 把 t分离出来,然后将t插入到头部位置 t->pre->next = t->next; t->next->pre = t->pre; t->val = value; //** t->pre = head; t->next = head->next; head->next = t; t->next->pre = t; return; } }private: int capacity; int size; DNode* head; DNode* tail; map<int,DNode*> mp;};
ac2 (C++ list + map)
考虑到c++ list本身就是个 双向链表,可以直接采用list(效率会比较差,不过能ac)
class LRUCache{public: LRUCache(int _capacity) { capacity = _capacity; size = 0; cachelist.clear(); mp.clear(); } int get(int key) { map<int,pair<int,int>>::iterator it= mp.find(key); if(it == mp.end()) //如果在Cache中不存在该key, 则返回-1 { return -1; } else { pair<int,int> t = it->second; pair<int,int> newPair(t.first, t.second); cachelist.remove(t); cachelist.push_front(newPair); return newPair.second; } } void put(int key, int value) { map<int,pair<int,int>>::iterator it= mp.find(key); if(it == mp.end()) //如果在Cache中不存在该key, 则返回-1 { if(size == capacity) //如果双向链表容量已满即缓存容量已满,则将最近不使用的节点即链表最后一个数据节点删除 { pair<int,int> tmp = cachelist.back(); cachelist.pop_back(); mp.erase(tmp.first); size--; } pair<int,int> newPair(key,value); cachelist.push_front(newPair); mp[key] = newPair; size++;//链表节点数++ }else{ // 当前put的可以存在,需要更新value pair<int,int> t = it->second; pair<int,int> newPair(key,value); cachelist.remove(t); cachelist.push_front(newPair); mp[t.first] = newPair; return; } }private: int capacity; int size; list<pair<int,int>> cachelist; map<int, pair<int,int>> mp;};
ac3
按照数据结构图的思想来写代码会容易很多
typedef struct node{ int key; int val; struct node* next; struct node* pre; node(int _key = -1, int _val = -1){ key = _key; val = _val; next = NULL; pre = NULL; }}Dnode;class LRUCache {public: int size; int cap; Dnode* head; Dnode* tail; map<int, Dnode*> mp; LRUCache(int capacity) { size = 0; cap =capacity; head = new Dnode; tail = new Dnode; head->next = tail; tail->pre = head; } int get(int key) { if(mp.count(key) == 0) return -1; Dnode* oldPos = mp[key]; int val = oldPos->val; //要返回的val Dnode* oldpre = oldPos->pre; oldPos->next->pre = oldpre; oldpre->next = oldPos->next; delete oldPos; mp.erase(key); Dnode* newPos = new Dnode(key,val); head->next->pre = newPos; newPos->next = head->next; newPos->pre = head; head->next = newPos; mp[key] = newPos; return val; } void put(int key, int value) { if(cap <= 0) return; int storeVal = get(key); if(storeVal != -1) { head->next->val = value; mp[key]->val = value; return; } if(size == cap) { Dnode* delNode = tail->pre; int delKey = delNode->key; Dnode* delpre = tail->pre->pre; delpre->next = tail; tail->pre= delpre; delete delNode; mp.erase(delKey); size --; } Dnode* newPos = new Dnode(key,value); head->next->pre = newPos; newPos->next = head->next; newPos->pre = head; head->next = newPos; mp[key] = newPos; size ++; }};
上面的代码,改进一下get方法(可以优化一点运行时间)
int get(int key) { if(mp.count(key) == 0) return -1; Dnode* oldPos = mp[key]; int val = oldPos->val; //要返回的val Dnode* oldpre = oldPos->pre; oldPos->next->pre = oldpre; oldpre->next = oldPos->next; //delete oldPos; //mp.erase(key); //Dnode* newPos = new Dnode(key,val); Dnode* newPos = oldPos; //直接更新 head->next->pre = newPos; newPos->next = head->next; newPos->pre = head; head->next = newPos; mp[key] = newPos;// 直接更新 return val;}
- 页面置换算法LRU实现--leetcode O(1)时间复杂度
- 页面置换算法--LFU算法实现-O(1)时间复杂度
- LRU页面置换算法Java实现
- C语言实现LRU页面置换算法
- 页面置换算法LRU
- 页面置换算法 LRU
- LRU页面置换算法
- LRU页面置换算法
- [Leetcode-146] LRU Cache 最近最少使用页面置换算法
- LRU页面置换算法模拟
- 模拟LRU页面置换算法
- LRU页面置换算法模拟
- 关于FIFO和LRU页面置换算法的实现
- LRU页面置换算法原理及Java代码的实现
- 转载:操作系统页面置换算法(opt,lru,fifo,clock)实现
- JAVA实现页面置换算法(OPT,FIFO,LRU)
- 操作系统页面置换算法(opt,lru,fifo,clock)实现
- java实现FIFO和LRU页面置换算法
- HttpClient获取响应内容类型Content-Type
- R语言爬虫-RCurl和XML学习笔记
- Mycat之——实现MySQL的读写分离
- PAT.Basic level.T.1006.换个格式输出整数
- js JSON 对象和字符创互转
- 页面置换算法LRU实现--leetcode O(1)时间复杂度
- Struts2的配置和获取相关servlet API的方法
- Ubuntu启动ssh报错:server responded algorithm negotiation field
- 微信支付问题记录(android)
- Java linkedHashMap构造方法
- 全排列生成算法:next_permutation
- 轻松复制360个人图书馆的文档
- adb调试实用命令
- HttpClient获取响应状态Status