題目:
運用你所掌握的數據結構,設計和實現一個 LRU (最近最少使用) 緩存機制。它應該支持以下操作: 獲取數據 get 和 寫入數據 put 。
獲取數據 get(key) - 如果關鍵字 (key) 存在於緩存中,則獲取關鍵字的值(總是正數),否則返回 -1。
寫入數據 put(key, value) - 如果關鍵字已經存在,則變更其數據值;如果關鍵字不存在,則插入該組「關鍵字/值」。當緩存容量達到上限時,它應該在寫入新數據之前刪除最久未使用的數據值,從而爲新的數據值留出空間。
示例:
LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 該操作會使得關鍵字 2 作廢
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 該操作會使得關鍵字 1 作廢
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
個人思路:
LRU 緩存機制可以通過哈希表輔以雙向鏈表實現,我們用一個哈希表和一個雙向鏈表維護所有在緩存中的鍵值對。
雙向鏈表按照被使用的順序存儲了這些鍵值對,靠近頭部的鍵值對是最久未使用的,而靠近尾部的鍵值對是最近使用的。
哈希表即爲普通的哈希映射(HashMap),通過緩存數據的鍵映射到其在雙向鏈表中的位置。
這樣以來,我們首先使用哈希表進行定位,找出緩存項在雙向鏈表中的位置,隨後將其移動到雙向鏈表的頭部,即可在 O(1)的時間內完成 get 或者 put 操作。
代碼:
class Tree{
int val;
int key;
Tree pre;
Tree next;
Tree(int key,int val){
this.key=key;
this.val=val;
}
}
class LRUCache {
int capacity;
HashMap<Integer,Tree> map=new HashMap();
Tree head;
Tree end;
public LRUCache(int capacity) {
this.capacity=capacity;
head=new Tree(0,0);
end=new Tree(100,100);
head.next=end;
end.pre=head;
}
public int get(int key) {
if(!map.containsKey(key)){
return -1;
}
Tree curtree=map.get(key);
int re=curtree.val;
curtree.pre.next=curtree.next;
curtree.next.pre=curtree.pre;
curtree.next=end;
curtree.pre=end.pre;
end.pre.next=curtree;
end.pre=curtree;
return re;
}
public void put(int key, int value) {
if(map.containsKey(key)){
Tree curtree=map.get(key);
curtree.pre.next=curtree.next;
curtree.next.pre=curtree.pre;
curtree.next=null;
curtree.pre=null;
Tree new_curtree=new Tree(key,value);
new_curtree.next=end;
new_curtree.pre=end.pre;
end.pre.next=new_curtree;
end.pre=new_curtree;
map.put(key,new_curtree);
}else{
Tree new_curtree=new Tree(key,value);
new_curtree.next=end;
new_curtree.pre=end.pre;
end.pre.next=new_curtree;
end.pre=new_curtree;
map.put(key,new_curtree);
if(map.size()>capacity){
Tree dele_tree=head.next;
int dele_key=dele_tree.key;
map.remove(dele_key);
head.next=dele_tree.next;
dele_tree.pre=null;
dele_tree.next=null;
head.next.pre=head;
}
}
}
}