ポータル:インタビュー質問16.25。LRUキャッシュ
タイトルの説明:
最も使用頻度の低いアイテムを削除する「最も使用頻度の低い」キャッシュを設計および構築します。キャッシュはキーから値にマップされ(特定のキーに対応する値を挿入および取得できるようにする)、初期化中に最大容量を指定する必要があります。キャッシュがいっぱいになると、最も使用頻度の低いアイテムが削除されます。
次の操作をサポートする必要があります。データの取得とデータの書き込み。
データの取得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+ LinkedListはJavaで直接使用されます(最下層は二重リンクリストです)。もちろん、マップはキーと値を格納しますが、LinkedListは使用されます。キーの有効期限を最も早い有効期限とともに保存します。テーブルの先頭にあります。
get操作の場合:キーがマップに存在しない場合、-1が返されます。存在する場合は、最初にリストからキーを削除し、リストの最後に追加してから、キーに対応する値を返します。
put操作の場合:最初に同じキーがマップに存在するかどうかを判別し、次にキーをリストから削除してリストの最後に再度追加します。次に、マップはputを実行して値を更新します。同じキーが存在しない場合は、マップがいっぱいかどうかを判断します。いっぱいの場合は、有効期限ポリシーが実行されます。リストは最初にヘッダーの値を削除し、マップはキーを削除してから追加します。(最初に含まれているかどうかを判断してから、いっぱいかどうかを判断する必要があるのはなぜですか?最初にいっぱいであると判断された場合、削除されたキーが必ずしも同じであるとは限らず、最終的に元のキーが更新されますが、現在のリストに削除されますヘッダーのキーが原因でエラーが発生しました)
たとえば、次の一連の例。
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.put(2, 3); // 如果先判断满, 该操作会使得密钥 1 作废,下一次get(1)就会返回-1
コード:
class LRUCache {
private int mapSize;
Map<Integer,Integer> maps;
LinkedList<Integer> list;
public LRUCache(int capacity) {
maps=new HashMap<Integer,Integer>(capacity);
list=new LinkedList<Integer>();
mapSize=capacity;
}
public int get(int key) {
if(maps.get(key)==null) return -1;
else{
list.remove(Integer.valueOf(key));
list.add(key);
return maps.get(key);
}
}
public void put(int key, int value) {
if(maps.containsKey(key)){
list.remove(Integer.valueOf(key));
//list.addLast(key);
}else if(maps.size()==mapSize){
maps.remove(list.removeFirst());
}
list.add(key);
maps.put(key,value);
}
}
この問題には多くの解決策があります。LinkedHashMapを直接使用することも、シングルリンクリストとダブルリンクリストの両方のリンクリストを自分で実装することもできます。