class LRUCache {
public:
//函数 get 和 put 必须以 O(1) 的平均时间复杂度运行
//保持把新鲜数据往链表头移动。新鲜的定义:刚被修改(put),或者访问过(get),就算新鲜,就需要放到链表头。
//过期键直接 pop_back(),链表节点越往后,越陈旧struct Node{int key, value;Node* left,* right;Node(){};Node(int k, int v):key(k), value(v), left(nullptr), right(nullptr){};};int n;unordered_map<int, Node*> mp; Node* L, *R;//利用虚拟的头节点和尾节点来帮助删除和插入LRUCache(int capacity) {n = capacity;L = new Node(-1, -1);R = new Node(-1, -1);L->right = R;R->left = L;}//p->left  p  p->rightvoid remove(Node* p){//删除p节点p->right->left = p->left;p->left->right = p->right;}//L p L->rightvoid insert(Node* p){//将p节点移动到虚拟头节点后面p->right = L->right;p->left = L;L->right->left = p;L->right = p;}int get(int key) {if (!mp.count(key)){return -1;}int v = mp[key]->value;remove(mp[key]);insert(mp[key]);return v;}void put(int key, int value) {if (mp.count(key)){mp[key]->value = value;remove(mp[key]);insert(mp[key]);}else{if (mp.size() == n){Node* p = R->left;remove(p);mp.erase(p->key);delete p;}//否则,插入(key, value)Node* p = new Node(key,value);mp[key] = p;insert(p);}}
};/*** Your LRUCache object will be instantiated and called as such:* LRUCache* obj = new LRUCache(capacity);* int param_1 = obj->get(key);* obj->put(key,value);*/

struct Node{int key;int val;int freq;//频率Node* left;Node* right;Node(): key(-1), val(-1), freq(0), left(nullptr), right(nullptr){}Node(int _k, int _v): key(_k), val(_v), freq(1), left(nullptr), right(nullptr){}
};struct FreqList{int freq;Node* vhead;Node* vtail;FreqList (int _f): freq(_f), vhead(new Node()), vtail(new Node()){vhead->right = vtail;vtail->left = vhead;}
};//虚构的头、尾节点
class LFUCache {
private:unordered_map<int, Node*> mp;//unordered_map<int, FreqList*> freq_map;//频率节点int n;int min_freq;
public:LFUCache(int capacity): n(capacity) {}//p->left p p->rightvoid remove(Node* p){//操作和LRU类似p->right->left = p->left;p->left->right = p->right;}void inserthead(Node* p){//放到同频率的对头int freq = p->freq;if (freq_map.find(freq) == freq_map.end()){//没找到这个频率的freq_map[freq] = new FreqList(freq);}//L p L->right//操作和LRU类似FreqList* L = freq_map[freq];p->right = L->vhead->right;p->left = L->vhead;L->vhead->right->left = p;L->vhead->right = p;}bool empty(FreqList* L){return L->vhead->right == L->vtail ? true: false;}int get(int key) {int res = -1;if (mp.find(key) != mp.end()){//找到了Node* p = mp[key];res = p->val;remove(p);p->freq++;if (empty(freq_map[min_freq])) min_freq++;//生成一个频率的双向链表inserthead(p);}return res;}void put(int key, int value) {if (n == 0) return;if (get(key) != -1){mp[key]->val = value;}else{if (mp.size() == n){//满了Node* p = freq_map[min_freq]->vtail->left;remove(p);mp.erase(p->key);delete p;}Node* p = new Node(key, value);mp[key] = p;min_freq = 1;//新加入的频率最低为1inserthead(p);}}
};/*** 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);*/

《每日一题》——146. LRU 缓存|460. LFU 缓存相关推荐

  1. lfu算法c语言,LeetCode算法系列 460. LFU 缓存机制

    力扣原题 460. LFU 缓存机制 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构. 实现 LFUCache 类:LFUCache(int capacity) - 用数据结构的容量 cap ...

  2. 460. LFU 缓存

    460. LFU 缓存 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构. 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 capacity ...

  3. ​ leetcode 460. LFU 缓存 hard​

    leetcode 460. LFU 缓存  hard 题目描述: 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构. 实现 LFUCache 类: LFUCache(int capacity) ...

  4. 学习笔记 | LeetCode 460. LFU缓存

    LeetCode 460. LFU缓存 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构.它应该支持以下操作:get 和 put. get(key)- 如果键存在于缓存中,则获取键的值(总是正 ...

  5. LeetCode 460. LFU缓存(哈希双链表)

    1. 题目 设计并实现最不经常使用(LFU)缓存的数据结构.它应该支持以下操作:get 和 put. get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1. put(ke ...

  6. LeetCode 460. LFU 缓存 -- 哈希查询+双向链表

    LFU 缓存 困难 634 相关企业 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构. 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 ca ...

  7. LeetCode 460. LFU缓存

    文章目录 题目描述 思路 实现 解法二 扩展 题目描述 实现一个LFU缓存(Least Frequently Used). 在需要移除元素时,移除最近访问频率最低的.可以对每个元素增加一个计数器,访问 ...

  8. 力扣 460. LFU 缓存

    题目来源:https://leetcode.cn/problems/lfu-cache/ 大致题意: 设计一个 LFU 缓存类: LFUCache(int capacity) - 用数据结构的容量 c ...

  9. lfu实现 java_LFU算法实现(460. LFU缓存)

    今天字节客户端三面问了这道题,没做出来.第一,之前没见过lfu,第二,要求O(1)时间,条件苛刻一点.只能说无缘字节. 言归正传,LFU算法:least frequently used,最近最不经常使 ...

最新文章

  1. Linux C编程--网络编程1--字节顺序和字节处理函数
  2. 温故(2):pass by value
  3. FLEX实例:GOOGLE地图.
  4. 【CI/CD1】jenkins
  5. SQL服务器引擎组件概览
  6. torch.nn模块介绍
  7. 第009讲 初识css 类选择器 id选择器 html选择器
  8. 微信小程序底部突起半圆设计
  9. matlab的mkdir创建新的文件夹,并把图像保存在该文件夹内
  10. android 代码混淆原理,Android 代码混淆
  11. 小波变换matlab代码,matlab小波变换代码
  12. 2020.12.28Excel(数字到BZZ)
  13. c语言苹果大小分级,苹果品质分级标准您知道吗?
  14. 刨根究底字符编码之八——Unicode编码方案概述
  15. matlab的containers.Map类型介绍
  16. 苹果ipad找不到服务器怎么办,找不到网络怎么办 ipad无法加入无线网络解决方法【详解】...
  17. 人力资源管理中的能力素质模型
  18. $STRM 空投和 Strategy Stakers 代币分配
  19. Python程序员面向对象技巧梳理
  20. python枚举算法流程图_算法-枚举

热门文章

  1. 阿里巴巴年度技术总结 - 人工智能在搜索的应用和实践
  2. Echo,Linux上最忧伤的命令(故事)
  3. 阿里云创建AccessKey 和 Access Key Secert
  4. Web防火墙(WAF)是什么?和传统防火墙区别是什么?
  5. SqlServer 如何插入图片和导出图片数据
  6. JS-变量提升与暂时性死区概念
  7. 当我们想要用LinkedIn领英开发客户时,如何设计填写职位头衔?
  8. Atitit 手机号码选号 规范 流程 attilax总结 v2 r99.docx
  9. python在医学中的应用_如何应用Python处理医学影像学中的DICOM信息
  10. C语言中p, *p, p, *p, **p的理解-初级