数据结构与算法面试题:实现一个 LRU 缓存,支持如下操作:获取值、更新值、删除键值对和插入键值对

数据结构与算法面试题:实现一个 LRU 缓存,支持如下操作:获取值、更新值、删除键值对和插入键值对

简介:实现一个 LRU 缓存,支持如下操作:获取值、更新值、删除键值对和插入键值对

算法思路

  1. 使用一个双向链表存储每个键值对,按照访问时间从早到晚依次排列,越晚访问的节点越靠近双向链表的头部。这里使用了 C++ 中的 list 模板类。

  2. 使用一个哈希表存储键和对应的节点指针,可以用 C++ 标准库中的 unordered_map 实现。

  3. 对于插入、更新、删除操作需要同时修改双向链表和哈希表。

  4. 当缓存已满时,在插入新的键值对之前,需要将最近最少使用的节点从双向链表中删除,并从哈希表中删除相应的键值对。

  • c++
#include <iostream>
#include <unordered_map>
#include <list>

using namespace std;

class LRUCache {
    
    
public:
    LRUCache(int capacity) {
    
     // 构造函数
        cap = capacity; // 缓存容量
    }
    
    int get(int key) {
    
     // 获取值操作
        if (cache.count(key)) {
    
     // 缓存命中
            auto it = cache[key]; // 从哈希表中找到对应的迭代器
            int val = it->second; // 取出键值对中的值
            recent.erase(it); // 将访问过的键位于链表头部,将其删除
            recent.push_front(key); // 将当前键放在链表头部
            cache[key] = recent.begin(); // 更新键在双向链表中的对应迭代器位置
            return val;
        }
        return -1; // 缓存未命中
    }
    
    void put(int key, int value) {
    
     // 更新值操作
        if (cache.count(key)) {
    
     // 若键已存在,则替换其值
            auto it = cache[key]; // 从哈希表中找到对应的迭代器
            recent.erase(it); // 将访问过的键位于链表头部,将其删除
        }
        else if (recent.size() == cap) {
    
     // 若链表已满,则删除最久未使用的键
            int old_key = recent.back(); // 查找链表尾部的键值并保留
            recent.pop_back(); // 删除链表尾部的键值对
            cache.erase(old_key); // 从哈希表中删除对应的键
        }
        recent.push_front(key); // 将当前键放在链表头部
        cache[key] = recent.begin(); // 更新键在双向链表中的对应迭代器位置
        cache[key]->second = value; // 更新键值对中的值
    }

private:
    int cap;
    unordered_map<int, list<int>::iterator> cache; // 哈希表,键为键值,值为双向链表中对应节点的迭代器
    list<int> recent; // 双向链表,存储键值
};

int main() {
    
    
    LRUCache lru_cache(2);
    lru_cache.put(1, 1);
    lru_cache.put(2, 2);
    cout << lru_cache.get(1) << endl; // 查询键1,返回1,并将该键移动到链表头部
    lru_cache.put(3, 3); // 插入键3,此时容量超出限制,删除最近最少使用的键2
    cout << lru_cache.get(2) << endl; // 查询键2,未命中,返回-1
    lru_cache.put(4, 4); // 插入键4,此时容量超出限制,删除最近最少使用的键1
    cout << lru_cache.get(1) << endl; // 查询键1,未命中,返回-1
    cout << lru_cache.get(3) << endl; // 查询键3,返回3,并将该键移动到链表头部
    cout << lru_cache.get(4) << endl; // 查询键4,返回4,并将该键移动到链表头部
    return 0;
}

  • java
import java.util.*;

class LRUCache {
    
    
    private int cap;
    private Map<Integer, Integer> cache; // 哈希表,键为键值,值为对应的值
    private Deque<Integer> recent; // 双向链表,存储键值

    public LRUCache(int capacity) {
    
     // 构造函数
        cap = capacity; // 缓存容量
        cache = new HashMap<>();
        recent = new LinkedList<>();
    }

    public int get(int key) {
    
     // 获取值操作
        if (cache.containsKey(key)) {
    
     // 缓存命中
            recent.remove(key); // 移除双向链表中的键
            recent.addFirst(key); // 将当前键放在链表头部
            return cache.get(key); // 返回值
        }
        return -1; // 缓存未命中
    }

    public void put(int key, int value) {
    
     // 更新值操作
        if (cache.containsKey(key)) {
    
     // 若键已存在,则替换其值
            recent.remove(key); // 移除双向链表中的键
        }
        else if (recent.size() == cap) {
    
     // 若链表已满,则删除最久未使用的键
            int old_key = recent.removeLast(); // 查找链表尾部的键值并保留
            cache.remove(old_key); // 从哈希表中删除对应的键值对
        }
        recent.addFirst(key); // 将当前键放在链表头部
        cache.put(key, value); // 更新键值对中的值
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        LRUCache lru_cache = new LRUCache(2);
        lru_cache.put(1, 1);
        lru_cache.put(2, 2);
        System.out.println(lru_cache.get(1)); // 查询键1,返回1,并将该键移动到链表头部
        lru_cache.put(3, 3); // 插入键3,此时容量超出限制,删除最近最少使用的键2
        System.out.println(lru_cache.get(2)); // 查询键2,未命中,返回-1
        lru_cache.put(4, 4); // 插入键4,此时容量超出限制,删除最近最少使用的键1
        System.out.println(lru_cache.get(1)); // 查询键1,未命中,返回-1
        System.out.println(lru_cache.get(3)); // 查询键3,返回3,并将该键移动到链表头部
        System.out.println(lru_cache.get(4)); // 查询键4,返回4,并将该键移动到链表头部
    }
}

猜你喜欢

转载自blog.csdn.net/qq_51447496/article/details/131170376