• 设计复杂度为O(1)的LRU缓存结构


    题目描述

    设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能

    • set(key, value):将记录(key, value)插入该结构
    • get(key):返回key对应的value值
    [要求]
    • set和get方法的时间复杂度为O(1)
    • 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
    • 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
      若opt=1,接下来两个整数x, y,表示set(x, y)
      若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1
      对于每个操作2,输出一个答案
    示例1
    输入
    复制
    [[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
    输出
    复制
    [1,-1]
    说明
    第一次操作后:最常使用的记录为("1", 1)
    第二次操作后:最常使用的记录为("2", 2),("1", 1)变为最不常用的
    第三次操作后:最常使用的记录为("3", 2),("1", 1)还是最不常用的
    第四次操作后:最常用的记录为("1", 1),("2", 2)变为最不常用的
    第五次操作后:大小超过了3,所以移除此时最不常使用的记录("2", 2),加入记录("4", 4),并且为最常使用的记录,然后("3", 2)变为最不常使用的记录
    
    完整代码
    #include <unordered_map>
    class Solution {
    public:
        
        // 维护一个有序单向链表,当有一个新的数据被访问时,从链表头部开始遍历链表:
        // 1 如果此数据之前已经在缓存中了,那么将其从原来的位置删除,并将其插入到头节点
        // 2 如果此数据之前不在缓存中:
        //   2.1 如果缓存未满,则直接将此节点插入到头节点
        //   2.2 如果缓存已满,则删除链表尾节点,将新的数据插入到头节点
        // 复杂度为O(n)
         
         
        // 使用散列表hashtable与双向链表的组合
        // 当要缓存某个数据的时候,先在链表中查找这个数据。如果没有找到,则直接将数据放到链表的尾部;如果找到了,我们就把它移动到链表的尾部
        // 当缓存空间不够,需要淘汰一个数据的时候,我们就直接将链表头部的结点删除
        // 复杂度为O(1)
        
        unordered_map<int, int> map;
        vector<int> cache;
        
        vector<int> LRU(vector<vector<int> >& operators, int k) {
            // write code here
            vector<int> result;
            for(int i = 0; i < operators.size(); i++){
                if(operators[i][0] == 1){
                    set(operators[i][1], operators[i][2], k);
                }else if(operators[i][0] == 2){
                    result.push_back(get(operators[i][1]));
                }
            }
            return result;
            
        }
        
        void set(int key, int value, int k){
            if(cache.size()== k){
                map.erase(cache[0]);
                cache.erase(cache.begin());
            }
            map[key] = value;
            // 这个时候应该先查找cache中是否存在key,如果存在就把它删除后放到尾部
            for(int i = 0; i < cache.size(); i++){
                if(cache[i] == key){
                    // 删除
                    cache.erase(cache.begin() + i);
                    break;
                }
            }
            // 放到尾部
            cache.push_back(key);
        }
        
        int get(int key){
            // 根本不存在或者已经被删除了
            if(map.find(key) == map.end()){
                return -1;
            }
            // 这个时候应该先查找cache中是否存在key,如果存在就把它删除后放到尾部
            for(int i = 0; i < cache.size(); i++){
                if(cache[i] == key){
                    // 删除
                    cache.erase(cache.begin() + i);
                    // 放到尾部
                    cache.push_back(key);
                    break;
                }
            }
            return map[key];
        }
    };
    
  • 相关阅读:
    springmvc 处理静态资源
    springmvc jsp 获取 上下文
    springmvc 如何设置首页
    servlet-mapping url-pattern / 和 /*区别
    nginx支持php
    openresty 变量
    git tag用法
    python 导入模块,__init__.py 的作用
    python 转码问题
    python装饰器
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13610815.html
Copyright © 2020-2023  润新知