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);
 */
相关推荐
禹凕5 小时前
快速幂算法详解与实战
python·算法
xxwl5855 小时前
高斯消元法异或版
人工智能·算法·机器学习
sylviiiiiia5 小时前
leetcode hot 100
python·算法·leetcode
OPEN-F6 小时前
ROS2系列教程:Gazebo插件(关节控制/IMU/激光雷达)
c++·python·数码相机·算法·机器人
luj_17686 小时前
虚实交融中的真实人物塑造
c语言·开发语言·网络·经验分享·算法
haolin123.7 小时前
STL vector底层揭秘:从构造到迭代器失效
开发语言·c++·算法
shehuiyuelaiyuehao7 小时前
算法37,位运算,两个整数之和(不用+符号)
算法
猎头南楼7 小时前
MFC 质量流量控制器中的控制算法设计与落地思考
人工智能·算法
来一碗刘肉面7 小时前
平衡二叉树的删除
数据结构·算法
wabs6667 小时前
关于二叉树【力扣199.二叉树的右视图的思考】
数据结构·c++·算法·leetcode·二叉树·层序遍历