设计并实现最不经常使用(LFU)缓存的数据结构。它应该支持以下操作:get 和 put。
get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。
put(key, value) - 如果键不存在,请设置或插入值。当缓存达到其容量时,它应该在插入新项目之前,使最不经常使用的项目无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,最近最少使用的键将被去除。
进阶:
你是否可以在 O(1) 时间复杂度内执行两项操作?
示例:
LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 去除 key 2
cache.get(2); // 返回 -1 (未找到key 2)
cache.get(3); // 返回 3
cache.put(4, 4); // 去除 key 1
cache.get(1); // 返回 -1 (未找到 key 1)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
我的代码 284ms
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache* obj = new LFUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
struct node
{
int x,y,z;//对于set x为key y为使用次数,z为最近使用时间, 对于map x为value y为使用次数,z为最近使用时间,
node(){}
node(int i,int j,int k){x=i;y=j;z=k;}
friend bool operator<(const node &n1,const node &n2)
{
if(n1.y<n2.y) return true;
else if(n1.y==n2.y&&n1.z<n2.z) return true;
else if(n1.y==n2.y&&n1.z==n2.z&&n1.x<n2.x) return true;
return false;
}
};
class LFUCache {
public:
int count,index,capa;
set<node>s;
unordered_map<int,node> m;
LFUCache(int capacity) {
capa=capacity;
count=0;
index=0;
}
void deal_same(unordered_map<int,node>::iterator &it1,int key,int value)
{
node n1(key,it1->second.y,it1->second.z);
set<node>::iterator it2=s.find(n1);
s.erase(it2);
n1.y++;
n1.z=index;
s.insert(n1);
it1->second.x=value;
it1->second.y++;
it1->second.z=index;
index++;
}
int get(int key) {
unordered_map<int,node>::iterator it1=m.find(key);
if(it1==m.end()) return -1;
else
{
deal_same(it1,key,it1->second.x);
return it1->second.x;
}
}
void put(int key, int value) {
if(capa==0) return;
unordered_map<int,node>::iterator it1=m.find(key);
if(it1==m.end())
{
if(count==capa)
{
node n1=*s.begin();
s.erase(s.begin());
m.erase(n1.x);
count--;
}
node n2(key,1,index);
s.insert(n2);
node n3(value,1,index);
m[key]=n3;
index++;
count++;
}
else
deal_same(it1,key,value);
}
};
网上的代码 256ms
class LFUCache {
public:
LFUCache(int capacity) {
cap_ = capacity;
min_freq_ = -1;
}
int get(int key) {
if (values_.count(key) == 0) {
return -1;
}
Node& node = values_[key];
freq_list_[node.freq].erase(node.iter);
++ node.freq;
freq_list_[node.freq].emplace_back(key);
node.iter = -- freq_list_[node.freq].end();
if (freq_list_[min_freq_].size() == 0) {
++min_freq_;
}
return node.value;
}
void put(int key, int value) {
if (cap_ <= 0) {
return;
}
if (get(key) != -1) {
values_[key].value = value;
return;
}
if (values_.size() >= cap_) {
auto& list = freq_list_[min_freq_];
int evicted_key = list.front();
list.pop_front();
values_.erase(evicted_key);
}
min_freq_ = 1;
auto& list = freq_list_[min_freq_];
list.emplace_back(key);
values_[key] = {value, min_freq_, -- list.end()};
}
private:
int cap_;
int min_freq_;
struct Node {
int value;
int freq;
list<int>::iterator iter;
};
unordered_map<int, Node> values_; // key - node
unordered_map<int, list<int>> freq_list_; // freq list_keys
};