460. LFU缓存

有一个疑问,当我的构造函数这个样定义的时候



Node(int _cnt, int _time, int _key, int _value) {
cnt = _cnt;
time = _time;
key = _key;
value = _value;
}


我这样调用unordered_map是不会通过编译 



int get(int key) {
if(capacity == 0) {
return -1;
}

auto it = key_value.find(key);
if(it == key_value.end()) {
return -1;
}

Node cache = key_value[key]; // 这一行不能通过编译,cache通过it->second却是能够正常赋值的

s.erase(cache);
cache.cnt++;
cache.time = ++time;
s.insert(cache);
it->second = cache;

return cache.value;
}


 

但是,当我构造函数这个样定义的时候



Node(){}
Node(int _cnt, int _time, int _key, int _value) {
cnt = _cnt;
time = _time;
key = _key;
value = _value;
}


 



Node cache = key_value[key];


 

却能够正确编译,记录一下

 

代码:

1 struct Node {
2 int cnt;
3 int time;
4 int key, value;
5
6 Node(){}
7 Node(int _cnt, int _time, int _key, int _value) {
8 cnt = _cnt;
9 time = _time;
10 key = _key;
11 value = _value;
12 }
13
14 bool operator < (const Node& t) const {
15 return t.cnt == cnt ? time < t.time: cnt < t.cnt;
16 }
17 };
18
19 class LFUCache {
20 int time;
21 unordered_map<int, Node> key_value;
22 set<Node> s;
23 int capacity;
24 public:
25 LFUCache(int _capacity) {
26 key_value.clear();
27 time = 0;
28 s.clear();
29 capacity = _capacity;
30 }
31
32 int get(int key) {
33 if(capacity == 0) {
34 return -1;
35 }
36
37 auto it = key_value.find(key);
38 if(it == key_value.end()) {
39 return -1;
40 }
41 Node cache = key_value[key];
42 s.erase(cache);
43 cache.cnt++;
44 cache.time = ++time;
45 s.insert(cache);
46 it->second = cache;
47
48 return cache.value;
49 }
50
51 void put(int key, int value) {
52 if(capacity == 0) {
53 return ;
54 }
55
56 auto it = key_value.find(key);
57
58 if(it == key_value.end()) {
59 if(key_value.size() == capacity) {
60 key_value.erase(s.begin()->key);
61 s.erase(s.begin());
62 }
63
64 Node node = Node(1, ++time, key, value);
65 key_value.insert(make_pair(key, node));
66 s.insert(node);
67
68 }
69 else {
70 Node tmp = key_value[key];
71 s.erase(tmp);
72 tmp.cnt += 1;
73 tmp.time = ++time;
74 tmp.value = value;
75 it->second = tmp;
76 s.insert(tmp);
77 }
78
79 }
80 };
81
82 /**
83 * Your LFUCache object will be instantiated and called as such:
84 * LFUCache* obj = new LFUCache(capacity);
85 * int param_1 = obj->get(key);
86 * obj->put(key,value);
87 */


 方法二:

每一个频率创建一个链表,然后还有一个unordered_map用作定位



struct Node {
int key;
int val;
int freq;
Node(){}
Node(int _key, int _val, int _freq) {
key = _key;
val = _val;
freq = _freq;
}
};

class LFUCache {
unordered_map<int, list<Node> > key_to_freq;
unordered_map<int, list<Node>::iterator> key_to_value;
int capacity;
int minfreq;

public:
LFUCache(int _capacity) {
capacity = _capacity;
key_to_freq.clear();
key_to_value.clear();
minfreq = 0;
}

int get(int key) {
if(capacity == 0) {
return -1;
}
auto iter = key_to_value.find(key);
if(iter == key_to_value.end()) {
return -1;
}
else {
list<Node>::iterator pos = iter->second;
int freq = pos->freq, val = pos->val;
key_to_freq[freq].erase(pos);

if(key_to_freq[freq].size() == 0) {
key_to_freq.erase(freq);
if(freq == minfreq) {
minfreq += 1;
}
}

key_to_freq[freq + 1].push_front(Node(key, val, freq + 1));
key_to_value[key] = key_to_freq[freq + 1].begin();
return val;
}
}

void put(int key, int value) {
if(capacity == 0) {
return ;
}
auto iter = key_to_value.find(key);
if(iter != key_to_value.end()) {
list<Node>::iterator pos = iter->second;
int freq = pos->freq, val = pos->val;
key_to_freq[freq].erase(pos);
key_to_value.erase(key);

if(key_to_freq[freq].size() == 0) {
key_to_freq.erase(freq);
if(freq == minfreq) {
minfreq += 1;
}
}

key_to_freq[freq + 1].push_front(Node(key, value, freq + 1));
key_to_value[key] = key_to_freq[freq + 1].begin();


return ;
}
else {
if(key_to_value.size() == capacity) {
Node pos = key_to_freq[minfreq].back();
int val = pos.val, freq = pos.freq;
key_to_value.erase(pos.key);
key_to_freq[minfreq].pop_back();
if(key_to_freq[minfreq].size() == 0) {
key_to_freq.erase(minfreq);
}
}

//Node node = new Node(key, value, 1);
key_to_freq[1].push_front(Node(key, value, 1));
key_to_value[key] = key_to_freq[1].begin();
minfreq = 1;
}
return ;
}
};

/**
* 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);
*/