【leetcode前500】460. LFU 缓存

此题有两个需要注意的点,最近-最少未使用。

比如说我们有几个键值对,那么,如果要淘汰一个的话按照题意“存在相同使用频率应该去除最近最久未使用的”,应当先比较计数器,不相等淘汰计数器最少的;若计数器相等,那么淘汰最晚加入的。

我们在类内部维护一个时间戳,只要进入一个操作内,时间戳就+1来维护时间序列。

剩下的是就是节点的更新工作,在本题刚开始时,准备使用堆来维护节点,以哈希表来维护键,但事实实际上用树状结构足够了,因为维护的代价都是log(n)。需要注意的就是节点的先删除再插入,在这个过程中,更新计数器、时间戳即可。

这里采用C++来编写。

#include <unordered_map>
#include <set>
struct Node{
public:
	int timestamp;
	int cnt;
	int key;
	int val;

	Node()= default;
	Node(int _key,int _val,int _timestamp,int _cnt):
	key(_key),val(_val),cnt(_cnt),timestamp(_timestamp){}
	bool operator<(const Node& other)const{
		if(cnt==other.cnt){
			return timestamp<other.timestamp;
		}
		return cnt<other.cnt;
	}

};

class LFUCache {
	int capacity;
	int timestamp;
	std::set<Node> node_set;
	std::unordered_map<int,Node> nodes;
public:
	LFUCache(int _capacity) {
		capacity=_capacity;
		timestamp=0;
	}

	int get(int key) {
		if(capacity<=0){
			return -1;
		}
		timestamp++;
		auto it=nodes.find(key);
		if(it==nodes.end()){
			return -1;
		}
		Node n=it->second;
		node_set.erase(n);
		n.cnt++;
		n.timestamp=timestamp;
		nodes[n.key]=n;
		node_set.insert(n);
		return n.val;
	}

	void put(int key, int value) {
		if(capacity<=0){
			return ;
		}
		timestamp++;
		auto it=nodes.find(key);

		if(it!=nodes.end()){
			Node n=it->second;
			node_set.erase(n);
			n.timestamp=timestamp;
			n.cnt++;
			n.val=value;
			node_set.insert(n);
			nodes[key]=n;
		}
		else{
			if(node_set.size()==capacity){
				auto first=node_set.begin();
				int k=first->key;
				node_set.erase(*first);
				nodes.erase(k);
			}
			Node node(key,value,timestamp,1);
			nodes[key]=node;
			node_set.insert(node);
		}

	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值