c++ - 结束迭代器减量的应用及意义
问题描述
int get(int key) {
if (m.count(key) == 0) return -1;
freq[m[key].second].erase(iter[key]);
freq[m[key].second].push_back(key);
iter[key] = --freq[m[key].second].end();
if (freq[minFreq].size() == 0) ++minFreq;
return m[key].first;
}
private:
int cap, minFreq;
unordered_map<int, pair<int, int>> m;
unordered_map<int, list<int>> freq;
unordered_map<int, list<int>::iterator> iter;
我在 Leetcode 问题之一上找到了这一系列的解决方案代码。这让我想知道在这种情况下,结束迭代器递减实际上意味着什么,以及在你编码时使用这种格式的时机是什么时候。作为一个 C++ 初学者,我认为如果它保持不变就好了
iter[key] = freq[m[key].second].end();
但是——真的让我很困惑。在上下文中,我们应该找到 LFU 缓存,并且该行应该是在频率列表中找到一个值的对应位置。
解决方案
--
操作在实际语句之前执行。
重要的
- 在您进一步研究
unordered_map
解决方案之前(我也重新实现了该解决方案):
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <unordered_map>
#include <list>
#include <utility>
static const struct LFUCache {
inline LFUCache(const int capacity) {
this->capacity = capacity;
size = 0;
}
inline const int get(const int key) {
if (values.find(key) == values.end()) {
return -1;
}
update(key);
return values[key].first;
}
inline void put(const int key, const int value) {
if (!capacity) {
return;
}
if (values.find(key) != values.end()) {
values[key].first = value;
update(key);
} else {
if (size == capacity) {
const ValueType evict = keys[least_freq_used].front();
keys[least_freq_used].pop_front();
values.erase(evict);
iters.erase(evict);
} else {
size++;
}
values[key] = {value , 1};
keys[1].emplace_back(key);
iters[key] = --keys[1].end();
least_freq_used = 1;
}
}
private:
using ValueType = std::uint_fast16_t;
ValueType capacity;
ValueType size;
ValueType least_freq_used = 0;
std::unordered_map<ValueType, std::list<ValueType>> keys;
std::unordered_map<ValueType, std::pair<ValueType, ValueType>> values;
std::unordered_map<ValueType, std::list<ValueType>::iterator>iters;
inline void update(const int key) {
const ValueType freqency = values[key].second;
const auto& iter = iters[key];
values[key].second++;
keys[freqency].erase(iter);
keys[freqency + 1].emplace_back(key);
iters[key] = --keys[freqency + 1].end();
if (keys[least_freq_used].empty()) {
least_freq_used++;
}
}
};
值得注意的是,双向链表是实现 LFU 缓存的正确方法。这是讨论板中基于 DLL 的有效解决方案之一:
struct DListNode {
int key;
int value;
int freq;
DListNode* prev;
DListNode* next;
DListNode(int k, int v) {
key = k;
value = v;
freq = 1;
prev = next = nullptr;
}
};
struct DList {
DListNode* sentinel;
int size;
DList() {
size = 0;
sentinel = new DListNode(-1, -1);
sentinel->prev = sentinel->next = sentinel;
}
void prepend(DListNode* node) {
node->next = sentinel->next;
node->prev = sentinel;
sentinel->next->prev = node;
sentinel->next = node;
++size;
}
DListNode* pop(DListNode* node = nullptr) {
if (size == 0) {
return nullptr;
}
if (node == nullptr) {
node = sentinel->prev;
}
node->prev->next = node->next;
node->next->prev = node->prev;
--size;
return node;
}
};
struct LFUCache {
unordered_map<int, DListNode*> nodes;
unordered_map<int, DList*> freqs;
int capacity;
int min_freq;
LFUCache(int capacity) {
this->capacity = capacity;
min_freq = 0;
}
void _update(DListNode* node) {
if (freqs.find(node->freq) == freqs.end()) {
freqs[node->freq] = new DList();
}
if (freqs.find(node->freq + 1) == freqs.end()) {
freqs[node->freq + 1] = new DList();
}
freqs[node->freq]->pop(node);
if (min_freq == node->freq && freqs[node->freq]->size == 0) {
++min_freq;
}
++node->freq;
freqs[node->freq]->prepend(node);
}
int get(int key) {
if (nodes.find(key) == nodes.end()) {
return -1;
}
DListNode* node = nodes[key];
_update(node);
return node->value;
}
void put(int key, int value) {
if (capacity == 0) {
return;
}
if (nodes.find(key) != nodes.end()) {
DListNode* node = nodes[key];
_update(node);
node->value = value;
} else {
if (nodes.size() == capacity) {
if (freqs.find(min_freq) == freqs.end()) {
freqs[min_freq] = new DList();
}
DListNode* node = freqs[min_freq]->pop();
if (node) {
nodes.erase(node->key);
}
}
DListNode* node = new DListNode(key, value);
nodes[key] = node;
if (freqs.find(1) == freqs.end()) {
freqs[1] = new DList();
}
freqs[1]->prepend(node);
min_freq = 1;
}
}
};
推荐阅读
- python - Pymatgen:如何将查询结果转换为结构
- java - 如何解决此 unregisterReceiver() 错误?
- matlab - Matlab循环优化 - 逻辑索引
- google-apps-script - 使用脚本在特定列中的新工作表中搜索和替换
- javascript - 从具有特定类的每个元素中获取文本,然后加起来
- multithreading - QSerialport 在 QThread 中被阻塞
- qt - 无框窗口,但带有按钮保持器
- java - 重复对象上的java休眠保存方法反映在原始对象中
- python-3.x - 为什么 Python 列表理解最后会打印一个“无”列表?
- c++ - 使用由字符串 C++ 定义的地图名称的地图