[146. LRU Cache](https://leetcode.com/problems/lru-cache/)
### 題目描述
Design a data structure that follows the constraints of a [Least Recently Used (LRU) cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU).
Implement the `LRUCache` class:
* `LRUCache(int capacity)` Initialize the LRU cache with **positive** size `capacity`.
* `int get(int key)` Return the value of the `key` if the `key` exists, otherwise return `-1`.
* `void put(int key, int value)` Update the value of the `key` if the `key` exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the `capacity` from this operation, **evict** the least recently used key.
The functions `get` and `put` must each run in `O(1)` average time complexity.
### 範例
**Example 1:**
```
Input
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]
Explanation
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // cache is {1=1}
lRUCache.put(2, 2); // cache is {1=1, 2=2}
lRUCache.get(1); // return 1
lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}
lRUCache.get(2); // returns -1 (not found)
lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}
lRUCache.get(1); // return -1 (not found)
lRUCache.get(3); // return 3
lRUCache.get(4); // return 4
```
**Constraints**:
* 1 <= `capacity` <= 3000
* 0 <= `key` <= 10^4^
* 0 <= `value` <= 10^5^
* At most 2 * 10^5^ calls will be made to `get` and `put`.
### 解答
#### C++
``` cpp=
class LRUCache {
public:
class Node {
public:
int key, val;
Node* prev, * next;
Node(int k, int v) {
this->key = k;
this->val = v;
}
};
Node* head, * tail;
int size, capacity;
unordered_map<int, Node*> dict;
list<int> cache;
LRUCache(int capacity) {
head = new Node(-1, -1);
tail = new Node(-1, -1);
head->next = tail;
tail->prev = head;
size = 0;
this->capacity = capacity;
}
int get(int key) {
/*
case 1: key exists
remove(key)
add2head(key, value)
case 2: key not exists
return -1
*/
if (dict.count(key) > 0) {
Node* node = dict[key];
remove(key);
add2head(key, node->val);
return node->val;
} else {
return -1;
}
}
void put(int key, int val) {
/*
case 1: key exists
remove(key)
add2head(key, value)
case 2: key not exists
add2head(key, value)
if (cache.size() > k) {
removeTail()
}
*/
if (dict.count(key) > 0) {
remove(key);
add2head(key, val);
} else {
add2head(key, val);
}
}
void remove(int key) {
Node* curr = dict[key];
Node* prev = curr->prev;
Node* next = curr->next;
prev->next = next;
next->prev = prev;
size --;
dict.erase(key);
}
void add2head(int key, int val) {
Node* newNode = new Node(key, val);
Node* next = head->next;
head->next = newNode;
newNode->next = next;
next->prev = newNode;
newNode->prev = head;
dict[key] = newNode;
size ++;
if (size > capacity) {
Node* LRU_Node = tail->prev;
remove(LRU_Node->key);
}
}
};
```
> [name=Jerry Wu][time=18 July, 2023]
#### Python
```python=
class LRUCache:
def __init__(self, capacity: int):
self.size = capacity
self.cache = OrderedDict()
def get(self, key: int) -> int:
if key not in self.cache:
return -1
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key not in self.cache:
if len(self.cache) >= self.size:
self.cache.popitem(last=False)
else:
self.cache.move_to_end(key)
self.cache[key] = value
```
> [name=Yen-Chi Chen][time=Tue, Jul 18, 2023]
### Reference
[回到題目列表](https://hackmd.io/@Marsgoat/leetcode_every_day)