码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-09-17 12:29:48      阅读:31      评论:0      收藏:0      [点我收藏+]

标签:查找   使用   ret   二次   散列表   方法   map   记录   双向   

题目描述

设计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];
    }
};

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

标签:查找   使用   ret   二次   散列表   方法   map   记录   双向   

原文地址:https://www.cnblogs.com/flyingrun/p/13610815.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!