LRU,一年前写过,最近看到好几个面经说写这题,复习一下。
之前的方法是用一个used(int[])数组来记录key,越早put或get的key在越左边。每次get时,如果不存在key直接返回-1,存在的话,在used数组找到key的下标,从这往右第一位开始,把used每一位往左移动,把used最右边置成这个key,意思就是这个key是最后使用的;put时候,如果容量超过了,把used数组第0位(使用时间最远的key)从map里删了,然后从下标1开始每个元素左移,把当前key放最右边;如果不超容量,直接把当前key放在used最靠右不为空的地方。
class LRUCache {
private int capacity;
private HashMap<Integer, Integer> map;
private int[] used;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap();
used = new int[capacity];
for (int i = 0; i < capacity; i++){
used[i] = -1;
}
}
public int get(int key) {//System.out.println(map.size());
if (map.containsKey(key)) {
int p = 0;
while (used[p] != key){
p++;
}
for (int i = p; i < map.size() - 1; i++){
used[i] = used[i + 1];
}
used[map.size() - 1] = key;
return map.get(key);
}
return -1;
}
public void put(int key, int value) {//System.out.println(key+" "+value);
map.put(key, value);//System.out.println(map.size());
if (map.size() > capacity) {
int k = used[0], v = map.get(k);//System.out.println(k+" "+v);
map.remove(k, v);
for (int i = 0; i < map.size() - 1; i++){
used[i] = used[i + 1];
}
used[map.size() - 1] = key;
} else {//System.out.println(map.size()-1);
int p = 0;
while (p < capacity && used[p] != key){
p++;
}
if (p < capacity) {
for (int i = p; i < map.size() - 1; i++){
used[i] = used[i + 1];
}
}
used[map.size() - 1] = key;
}
}
}
然后现在发现直接用LinkedHashMap就可以了,因为可以保存put进去元素的顺序。每次get/put,如果key存在,先删了再塞进去;如果超过容量,删除第一个key(用迭代器拿到keySet的第一个元素)
class LRUCache {
Map<Integer, Integer> map;
int limit;
public LRUCache(int capacity) {
map = new LinkedHashMap<>();
limit = capacity;
}
public int get(int key) {
if (map.containsKey(key)) {
int value = map.get(key);
map.remove(key);
map.put(key, value);
return value;
}
return -1;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
map.remove(key);
}
map.put(key, value);
if(map.size() > limit){
Map.Entry<Integer, Integer> first = map.entrySet().iterator().next();
map.remove(first.getKey());
}
}
}