[LeetCode] Interview Question 16.25. LRU Cache

Portal: Interview Question 16.25. LRU Cache
Title description:
Design and build a "least recently used" cache that will delete the least recently used items. The cache should be mapped from key to value (allowing you to insert and retrieve the value corresponding to a specific key), and specify the maximum capacity during initialization. When the cache is full, it should delete the least recently used items.

It should support the following operations: Get data get and write data put.

Get data get(key)-If the key (key) exists in the cache, get the value of the key (always a positive number), otherwise return -1.
Write data put(key, value)-If the key does not exist, write its data value. When the cache capacity reaches the upper limit, it should delete the least recently used data value before writing new data to make room for the new data value.

Test sample:

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

Idea: The idea of ​​LRU is nothing more than linked list + map. HashMap + LinkedList is used directly in Java (the bottom layer is a double-linked list). Of course, map stores keys and values, while LinkedList is used to store the expiration order of keys, with the earliest expiration time. At the head of the table.

For get operations : if the key does not exist in the map, -1 is returned. If it exists, remove the key from the list first, add it to the end of the list, and then return the value corresponding to the key.
For the put operation : first determine if the same key exists in the map, then remove the key from the list and add it to the end of the list again, and then the map executes put to update the value. If the same key does not exist, judge whether the map is full or not. If it is full, the expiration policy is executed. The list first removes the value of the header, the map removes the key, and then adds it. ( Why is it necessary to judge whether it is contained first and then judge whether it is full? Imagine that if it is judged to be full first, then the removed key is not necessarily the same key, which will eventually cause the original key to be updated, but it will be deleted to the current list The key of the header caused an error )

For example, the following set of examples.

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.put(2, 3);    // 如果先判断满, 该操作会使得密钥 1 作废,下一次get(1)就会返回-1

Code:

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);
    }
}

There are many solutions to this problem, you can also use LinkedHashMap directly, or you can implement a linked list yourself, both single and double linked lists.

Guess you like

Origin blog.csdn.net/dl962454/article/details/113741749