一、Problem
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.
The cache is initialized with a positive capacity.
Follow up:
Could you do both operations in O(1) time complexity?
LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
二、Solution
方法一:暴力做法
直接用 Map + LinkedList 做:
- put 時,檢查 key 是否有對應的 v
- 如果有,則覆蓋掉 Map 中的值,並且 q 的大小不能查過 cap,如果超了,pollFirst
- 否則,map 添加鍵值對
- get 時,也是先判空,此時的 key 爲使用過,所以要變新。
刪除操作耗費時間…
class LRUCache {
Map<Integer, Integer> mp;
ArrayDeque<Integer> q;
int cap;
public LRUCache(int capacity) {
mp = new HashMap<>(capacity);
q = new ArrayDeque<>();
cap = capacity;
}
public int get(int key) {
Integer v = mp.get(key);
if (v != null) {
q.remove(key);
q.add(key);
return v;
}
return -1;
}
public void put(int key, int value) {
Integer v = mp.get(key);
if (v != null) {
q.remove(key);
q.add(key);
} else if (q.size() < cap){
q.add(key);
} else {
int oldKey = q.pollFirst();
q.add(key);
mp.remove(oldKey);
}
mp.put(key, value);
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:雙向鏈表 + Map
- 定義一個 Node 內部類,存儲 k、v、pre、next
- map 就存儲 <K, Node> 類型的鍵值對,這樣就可以通過 k 用 的時間找到 v,然後通過修改指針的指向來刪除結點和添加結點。
複雜度分析
- 時間複雜度:,
- 空間複雜度:,