LeetCode:LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.

set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

LRU.h

#include <map>
#include <iostream>
using namespace std;

struct ListNode
{
	int key;
	int value;
	ListNode* next;
	ListNode* pre;
	ListNode(int key,int val):key(key),value(val){next = NULL; pre = NULL;}
};

class LRUCache
{
public:
	LRUCache(int capacity);
	~LRUCache();

	int get(int key);
	void set(int key,int value);

private:
	
	ListNode* head;
	ListNode* end;
	int capacity;
	map<int, ListNode*> cache;
};
LRU.cpp

#include "LRU.h"

LRUCache::LRUCache(int capacity)
{
	this->capacity = capacity;
	//初始化头尾指针
	head = new ListNode(0,0);
	end = head;
}

LRUCache::~LRUCache()
{
	cache.clear();
	//析构
	while(head!=NULL)
	{
		end = head;
		head = head->next;
		delete end;
	}
}

int LRUCache::get(int key)
{
	map<int , ListNode*>::iterator iTemp = cache.find(key);
	if(iTemp == cache.end())
		return -1;
	if(iTemp -> second != head->next)
	{

		if(iTemp->second == end)
		{
			//如果当前指针为尾指针,把尾指针向前一位
			end = end->pre;
			end -> next =NULL;				
		}
		else
		{
			//将iTemp的前后节点相连
			iTemp -> second ->next->pre = iTemp->second->pre;
			iTemp -> second ->pre ->next = iTemp->second->next;
		}
		//将iTemp插入head之后
		iTemp -> second -> next = head -> next;
		iTemp -> second -> pre = head;
		head -> next = iTemp -> second;
		iTemp -> second -> next->pre = iTemp ->second;
	}
	//测试输出
	ListNode* t = head->next;
	while(t!=NULL)
	{
		cout<<"("<<t->key<<","<<t->value<<")\t";
		t = t->next;
	}
	cout<<endl;

	return iTemp -> second -> value;
}

void LRUCache::set(int key, int value)
{
	if(capacity == 0)
		return ;
	map<int , ListNode*>::iterator iTemp = cache.find(key);
	//key不存在
	if(iTemp == cache.end())
	{
		ListNode* plnNew = new ListNode(key,value);			
		if(cache.size() == 0)
			end = plnNew;
		//新节点加入头部
		plnNew -> next = head->next;
		plnNew -> pre = head;
		head -> next = plnNew;
		if(plnNew -> next !=NULL)
			plnNew -> next ->pre = plnNew;

		//删除尾节点以及map中的pair
		if(cache.size() >= capacity)
		{
			ListNode* plnTemp = end;
			end = end -> pre;
			end->next = NULL;
			cache.erase(plnTemp->key);
			delete plnTemp;
		}
		//插入新pair
		pair<int,ListNode*> pNew(key,plnNew);
		cache.insert(pNew);
	}
	else
	{
		iTemp->second->value = value;
		//如果当前节点不是头结点
		if(iTemp -> second != head->next)
		{
			if(iTemp->second == end)
			{
				//若当前节点为尾节点
				end = end->pre;
				end -> next =NULL;				
			}
			else
			{
				//将当前节点的前后节点相连
				iTemp -> second ->next->pre = iTemp->second->pre;
				iTemp -> second ->pre ->next = iTemp->second->next;
			}
			//将当前节点插入头部
			iTemp -> second -> next = head -> next;
			iTemp -> second -> pre = head;
			head -> next = iTemp -> second;
			iTemp -> second -> next->pre = iTemp ->second;
		}

	}
	//测试输出
	ListNode* t = head->next;
	while(t!=NULL)
	{
		cout<<"("<<t->key<<","<<t->value<<")\t";
		t = t->next;
	}
	cout<<endl;
}

已AC  316ms

注意:

1、找到的节点为尾节点时,需要更新尾指针(这点可以改进为:把end改为tail作为一个尾指针 下述方法将提到)

方法二:改成尾指针

#include <map>
#include <iostream>
using namespace std;

struct ListNode
{
	int key;
	int value;
	ListNode* next;
	ListNode* pre;
	ListNode(int key,int val):key(key),value(val){next = NULL; pre = NULL;}
};

class LRUCache
{
public:
	LRUCache(int capacity);
	~LRUCache();

	int get(int key);
	void set(int key,int value);

private:
	
	ListNode* head;
	ListNode* tail;
	int capacity;
	map<int, ListNode*> cache;
};
#include "LRU.h"

LRUCache::LRUCache(int capacity)
{
	this->capacity = capacity;
	//初始化头尾指针
	head = new ListNode(0,0);
	tail = new ListNode(0,0);
	head -> next = tail;
	tail -> pre = head;
	cache.clear();
}

LRUCache::~LRUCache()
{
	cache.clear();
	//析构
	while(head!=NULL)
	{
		tail = head;
		head = head->next;
		delete tail;
	}
}

int LRUCache::get(int key)
{
	map<int , ListNode*>::iterator iTemp = cache.find(key);
	if(iTemp == cache.end())
		return -1;
	if(iTemp -> second != head->next)
	{

		//将iTemp的前后节点相连
		iTemp -> second ->next->pre = iTemp->second->pre;
		iTemp -> second ->pre ->next = iTemp->second->next;
		
		//将iTemp插入head之后
		iTemp -> second -> next = head -> next;
		iTemp -> second -> pre = head;
		head -> next = iTemp -> second;
		iTemp -> second -> next->pre = iTemp ->second;
	}
	//测试输出
	ListNode* t = head->next;
	while(t!=NULL)
	{
		cout<<"("<<t->key<<","<<t->value<<")\t";
		t = t->next;
	}
	cout<<endl;

	return iTemp -> second -> value;
}

void LRUCache::set(int key, int value)
{
	if(capacity == 0)
		return ;
	map<int , ListNode*>::iterator iTemp = cache.find(key);
	//key不存在
	if(iTemp == cache.end())
	{
		ListNode* plnNew = new ListNode(key,value);			
		
		//新节点加入头部
		plnNew -> next = head->next;
		plnNew -> pre = head;
		head -> next = plnNew;
		plnNew -> next ->pre = plnNew;

		//删除尾节点以及map中的pair
		if(cache.size() >= capacity)
		{
			ListNode* plnTemp = tail -> pre;
			tail -> pre = tail ->pre -> pre;
			tail->pre->next = tail;
			cache.erase(plnTemp->key);
			delete plnTemp;
		}
		//插入新pair
		pair<int,ListNode*> pNew(key,plnNew);
		cache.insert(pNew);
	}
	else
	{
		iTemp->second->value = value;
		//如果当前节点不是头结点
		if(iTemp -> second != head->next)
		{
			//将当前节点的前后节点相连
			iTemp -> second ->next->pre = iTemp->second->pre;
			iTemp -> second ->pre ->next = iTemp->second->next;
			
			//将当前节点插入头部
			iTemp -> second -> next = head -> next;
			iTemp -> second -> pre = head;
			head -> next = iTemp -> second;
			iTemp -> second -> next->pre = iTemp ->second;
		}

	}
	//测试输出
	ListNode* t = head->next;
	while(t!=NULL)
	{
		cout<<"("<<t->key<<","<<t->value<<")\t";
		t = t->next;
	}
	cout<<endl;
}

已AC 340ms



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值