LeetCode - LRU Cache
来源:互联网 发布:蜂窝移动数据用量清零 编辑:程序博客网 时间:2024/06/05 20:54
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 set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(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.
需要注意的是,在get和set操作后,被操作的节点就应该是最新用过的节点,应该移到最后面。
另外,需要注意linked list的操作,比如删除头节点,尾节点,capacity只有1这种情况都应该考虑到。
public class LRUCache { private int capacity; private int size; private Node first; private Node last; private HashMap<Integer, Node> map; class Node{ int key; int value; Node prev, next; public Node(int key, int val){ this.key = key; this.value = val; prev = null; next = null; } } public LRUCache(int capacity) { this.map = new HashMap<Integer, Node>(); this.capacity = capacity; this.size = 0; } public int get(int key) { if(map.containsKey(key)){ Node current = map.get(key); if(current!=last){ if(current==first){ first = first.next; first.prev = null; } else{ current.next.prev = current.prev; current.prev.next = current.next; } last.next = current; current.prev = last; current.next = null; last = current; } return current.value; } return -1; } public void set(int key, int value) { if(map.containsKey(key)){ Node current = map.get(key); if(current!=last){ if(current==first){ first = first.next; if(first!=null) first.prev = null; } else{ current.next.prev = current.prev; current.prev.next = current.next; } last.next = current; current.prev = last; current.next = null; last = current; } current.value = value; } else{ Node current = new Node(key, value); map.put(key, current); if(size<capacity){ if(first==null){ first = current; last = current; } else{ current.prev = last; last.next = current; last = last.next; } size++; } else{ Node tmp = first; first = first.next; if(first!=null) first.prev = null; if(first==null){ first = current; last = current; } else{ current.prev = last; last.next = current; last = last.next; } map.remove(tmp.key); } } }}
上面的代码有很多重复代码,比如删除节点之类的,所以,可以有两个remove和add函数,remove函数删除任意一个节点,add函数把一个节点加到list的末尾,两个函数都相应地更新size和hashmap。代码如下:
public class LRUCache { private int capacity; private int size; private Node first; private Node last; private HashMap<Integer, Node> map; class Node{ int key; int value; Node prev, next; public Node(int key, int val){ this.key = key; this.value = val; prev = null; next = null; } } public LRUCache(int capacity) { this.map = new HashMap<Integer, Node>(); this.capacity = capacity; this.size = 0; } public void remove(Node node){ if(node==first){ first = first.next; if(first!=null) first.prev = null; else last=null; } else if(node == last){ last = last.prev; if(last!=null) last.next = null; else first = null; } else{ node.prev.next = node.next; node.next.prev = node.prev; } map.remove(node.key); size--; } public void add(Node node){ if(first==null || last==null){ last = node; first = node; } else{ last.next = node; node.prev = last; last = last.next; } map.put(node.key, node); size++; } public int get(int key) { if(map.containsKey(key)){ Node current = map.get(key); if(current!=last){ remove(current); add(current); } return current.value; } return -1; } public void set(int key, int value) { if(map.containsKey(key)){ Node current = map.get(key); if(current!=last){ remove(current); add(current); } current.value = value; } else{ Node current = new Node(key, value); if(size>=capacity) remove(first); add(current); } }}
以下是C++的版本:
第一个版本是自己定义list,自己定义list node,然后用unordered_map做的,注意,这里所有在JAVA里面直接保存的node引用都要变成node指针。即全部是指针操作了, 并且在这里所有的node都是用new定义的,不然node的有效范围就只是当前函数模块,但是用node定义的话,在彻底删除节点时,需要delete这个node:
class Node{public: int key; int value; Node* prev; Node* next; Node(int k, int v){ this->key = k; this->value = v; prev = NULL; next = NULL; }};class LRUCache{private: unordered_map<int, Node*> map; Node* first; Node* last; int capacity; int size;public: LRUCache(int capacity) { first = NULL; last = NULL; this->capacity = capacity; this->size = 0; } void removeNode(Node* node){ if(node==first){ first = first->next; if(first!=NULL) first->prev = NULL; if(first==NULL) last = NULL; } else if(node==last){ last = last->prev; if(last!=NULL) last->next = NULL; if(last==NULL) first = NULL; } else{ node->prev->next = node->next; node->next->prev = node->prev; } size--; map.erase(node->key); } void add(Node* node){ if(first == NULL){ first = node; last = node; } else{ last->next = node; node->prev = last; last = last->next; } size++; map[node->key] = node; } int get(int key) { if(map.find(key)!=map.end()){ Node* current = map[key]; removeNode(current); add(current); return current->value; } else return -1; } void set(int key, int value) { if(map.find(key)!=map.end()){ Node* current = map[key]; removeNode(current); add(current); current->value = value; } else{ if(size==capacity){ Node* tdl = first; removeNode(tdl); delete tdl; } Node* current = new Node(key, value); add(current); } }};
第二个版本是用STL里面的list做的,因为STL里面list是双向链表,forward_list是单向链表,所以不用自己定义list,直接用STL提供的模板做,注意iterator是指向模板内节点的指针:
class Node{public: int key; int value; Node(int k, int v) : key(k), value(v){}};class LRUCache{private: unordered_map<int, list<Node>::iterator> map; list<Node> cache; int capacity;public: LRUCache(int capacity) { this->capacity = capacity; } void MoveToHead(int key){ Node update = *map[key]; cache.erase(map[key]); cache.push_front(update); map[key] = cache.begin(); } int get(int key) { if(map.find(key)!=map.end()){ MoveToHead(key); return map[key]->value; } else return -1; } void set(int key, int value) { if(map.find(key)!=map.end()){ MoveToHead(key); map[key]->value = value; } else{ if(cache.size()==capacity){ map.erase(cache.back().key); cache.pop_back(); } Node current(key, value); cache.push_front(current); map[key] = cache.begin(); } }};
- LeetCode LRU 缓存 LRU Cache
- LRU Cache | leetcode
- Leetcode: LRU Cache
- LeetCode:LRU Cache
- Leetcode: LRU Cache
- [LeetCode] LRU Cache
- leetcode之LRU Cache
- [LeetCode]LRU Cache
- [LeetCode] LRU Cache
- leetcode LRU Cache
- LeetCode题解:LRU Cache
- LeetCode | LRU Cache
- Leetcode: LRU Cache
- [LeetCode] LRU Cache
- LeetCode OJ:LRU Cache
- Leetcode LRU Cache
- LeetCode - LRU Cache
- [Leetcode] LRU Cache (Java)
- 两个很长的16进制字符串怎么进行异或运算
- 黑马程序员_java基础自学反射
- 黑马程序员_java基础自学经典程序记录
- 黑马程序员_java基础自学反射的优点
- Using label elements to associate text labels with form controls
- LeetCode - LRU Cache
- 多线程
- String类
- 异常
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 6 Assignment: hash table and heap
- 常见进程的调度算法
- 段寄存器的“前世今生”
- 算法之动态规划
- Intel Media SDK H264 encoder GOP setting