当前位置: 首页 > article >正文

leetcode 面试150之 156.LUR 缓存

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

题目重点:O(1)实现查找和删除

O(1)查找我们可以通过unordered_map底层哈希表来实现
这里我们如果缓存满了还得删除最久未使用关键字 ,所以我们得使用一个O(1)维护的“使用队列”,数组我们无法实现O(1)删除,而双向链表能实现O(1)删除,但是无法实现O(1)查询

所以我们这里用到了unordered_map<int,listnode*>映射为listnode*,通过map去实现O(1)查询
而listnode*双向链表实现O(1)插入和删除

起初我并未想到用双向链表而是用deque去维护“使用队列”,后者在维护队列无法做到O(1),包超时的

上代码:

class LRUCache {
public:
	struct listnode{
		int key;
		int val;
		listnode* pre;
		listnode* next;
		listnode(int k,int v):key(k),val(v),pre(nullptr),next(nullptr){}
	};
	int max_;                          //最大空间
	listnode* head;                    //头哨兵节点
	listnode* tail;                    //尾哨兵节点
	unordered_map<int,listnode*> dp;   //精华

    //初始化    
    LRUCache(int capacity) 
    {
      max_=capacity;
      head=new listnode(0,0);
	  tail=new listnode(0,0);
	  head->next=tail;
	  tail->pre=head;
    }

    //双向链表头插法 将处理的node节点 使用优先级提高
    void addnode(listnode* node)
    {
        node->next=head->next;
        head->next->pre=node;
        head->next=node;
        node->pre=head;
	}

    //断开node节点 并未delete  
	void remove_node(listnode* node)
	{
		node->pre->next=node->next;
		node->next->pre=node->pre;
	}


    //查询数据
    int get(int key) 
    {
        if(dp.count(key))          //查询成功 提高该节点的“使用队列”优先级
        {
        	remove_node(dp[key]);
        	addnode(dp[key]);
        	return dp[key]->val;
		}
		else return -1;
    }

    //插入数据
    void put(int key, int value) 
    {
        if(dp.count(key))
        {
        	dp[key]->val=value;    //已经存在   更新val后,取走节点后插入头  提高优先级
        	remove_node(dp[key]);
        	addnode(dp[key]);
		}
		
        //key不存在
        else
		{
			if(max_==dp.size())          //空间已满  删除优先级低节点 也就是 tail->pre
            {
				listnode* temp=tail->pre;
				remove_node(temp);
				dp.erase(temp->key);
				delete temp;               //释放内存
			}

            //无论空间是否够 都需要插入这个key节点
			listnode* node=new listnode(key,value); 
			addnode(node);
			dp.insert({key,node});
		}
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */


http://www.kler.cn/a/409201.html

相关文章:

  • 【npm设置代理-解决npm网络连接error network失败问题】
  • java 老矣,尚能饭否?
  • ES6 、ESNext 规范、编译工具babel
  • uni-app 界面TabBar中间大图标设置的两种方法
  • 编程之路,从0开始:文件操作(2)
  • 搜索引擎中广泛使用的文档排序算法——BM25(Best Matching 25)
  • c++中mystring运算符重载
  • 韩顺平 一周学会Linux | Linux 实操篇-实用指令
  • Python知识点精汇:集合篇精解!
  • 【大数据技术与开发实训】携程景点在线评论分析
  • HTMLCSS:翻书加载效果
  • 解!决!vscode!Path Intellisense 失效!不起作用问题!!
  • 机器学习实战笔记34-38:gridsearchcv的进阶使用,无监督学习:kmeans、DBSCAN
  • web网络安全系统
  • 深入浅出:大数据架构中的流处理与实时分析
  • 微服务系列概览
  • Momenta C++面试题及参考答案
  • Vue进阶面试题目(一)
  • vue3 + elementPlus 日期时间选择器禁用未来及过去时间
  • 【弱监督语义分割】Self-supervised Image-specific Prototype Exploration for WSSS 论文阅读
  • Leetcode 164.最大间距
  • c++视频图像处理
  • Linux连接网络的三种方式
  • 【JavaEE初阶 — 多线程】定时器的应用及模拟实现
  • 设计模式——拦截过滤器模式
  • ISAAC Gym 7. 使用箭头进行数据可视化