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 ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 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),包超时的

上代码:

cpp 复制代码
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);
 */
相关推荐
想跑步的小弱鸡2 小时前
Leetcode hot 100(day 3)
算法·leetcode·职场和发展
xyliiiiiL3 小时前
ZGC初步了解
java·jvm·算法
爱的叹息4 小时前
RedisTemplate 的 6 个可配置序列化器属性对比
算法·哈希算法
独好紫罗兰4 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法
每次的天空5 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
请来次降维打击!!!6 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
qystca6 小时前
蓝桥云客 刷题统计
算法·模拟
别NULL6 小时前
机试题——统计最少媒体包发送源个数
c++·算法·媒体
weisian1516 小时前
Java常用工具算法-3--加密算法2--非对称加密算法(RSA常用,ECC,DSA)
java·开发语言·算法
程序员黄同学8 小时前
贪心算法,其优缺点是什么?
算法·贪心算法