他說我們要設計一個LRU Cache (Least Recently Used Cache),時間複雜度為O(1),而且需要支援兩個動作。
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]
LRUCache lru = new LRUCache(2); // 容量 = 2
lru.put(1, 1); // cache = {1=1}
lru.put(2, 2); // cache = {2=2, 1=1} (2最近被用)
lru.get(1); // return 1 → cache = {1=1, 2=2} (1最近被用)
lru.put(3, 3); // 容量滿了刪掉最舊的 key=2 → cache = {3=3, 1=1}
lru.get(2); // 因為2被淘汰了所以return -1
lru.put(4, 4); // 容量滿了刪掉最舊的 key=1 → cache = {4=4, 3=3}
lru.get(1); // 因為1被淘汰了所以return -1
lru.get(3); // return 3 → cache = {3=3, 4=4}
lru.get(4); // return 4 → cache = {4=4, 3=3}
這題我想到的是HashMap+雙向鏈表,HashMap來存key對應的Node,然後雙向鏈表來管存取他們的順序,讓我們可以插入新的頭刪掉舊的尾。
class LRUCache {
class Node {
int key, val;
Node prev, next;
Node(int key, int val) {
this.key = key;
this.val = val;
}
}
private int cap;
private HashMap<Integer, Node> map;
private Node head, tail;
public LRUCache(int capacity) {
this.cap = capacity;
this.map = new HashMap<>();
//初始化head和tail
head = new Node(-1, -1);
tail = new Node(-1, -1);
head.next = tail;
tail.prev = head;
}
// 把節點移到頭部,變成最新的頭
private void moveToHead(Node node) {
remove(node);
insertToHead(node);
}
// 插入到 head 後面
private void insertToHead(Node node) {
Node nextNode = head.next;
head.next = node;
node.prev = head;
node.next = nextNode;
nextNode.prev = node;
}
// 從鏈表中刪除節點
private void remove(Node node) {
Node p = node.prev;
Node n = node.next;
p.next = n;
n.prev = p;
}
//查HashMap 找不到回傳-1;找到就取出來一道最新的位置,回傳他的值
public int get(int key) {
if (!map.containsKey(key)) return -1;
Node node = map.get(key);
moveToHead(node); // 更新最近使用
return node.val;
}
//key 已存在:更新值,移到最近使用。
//key 不存在:容量滿了就刪掉最尾,然後從map刪掉。不然就建立一個節點放到最前,加入map
public void put(int key, int value) {
if (map.containsKey(key)) {
// 已存在 → 更新值 + 移到頭
Node node = map.get(key);
node.val = value;
moveToHead(node);
} else {
if (map.size() == cap) {
// 滿了,移除尾巴前一個 (最久未使用的那一個)
Node lru = tail.prev;
remove(lru);
map.remove(lru.key);
}
// 插入新節點
Node newNode = new Node(key, value);
insertToHead(newNode);
map.put(key, newNode);
}
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
執行成功