//请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。
//
// 实现 LFUCache 类:
//
//
// LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象
// int get(int key) - 如果键 key 存在于缓存中,则获取键的值,否则返回 -1 。
// void put(int key, int value) - 如果键 key 已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量
//capacity 时,则应该在插入新项之前,移除最不经常使用的项。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近最久未使用 的键。
//
//
// 为了确定最不常使用的键,可以为缓存中的每个键维护一个 使用计数器 。使用计数最小的键是最久未使用的键。
//
// 当一个键首次插入到缓存中时,它的使用计数器被设置为 1 (由于 put 操作)。对缓存中的键执行 get 或 put 操作,使用计数器的值将会递增。
//
// 函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
//
//
//
// 示例:
//
//
//输入:
//["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get",
//"get"]
//[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
//输出:
//[null, null, null, 1, null, -1, 3, null, -1, 3, 4]
//
//解释:
//// cnt(x) = 键 x 的使用计数
//// cache=[] 将显示最后一次使用的顺序(最左边的元素是最近的)
//LFUCache lfu = new LFUCache(2);
//lfu.put(1, 1); // cache=[1,_], cnt(1)=1
//lfu.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
//lfu.get(1); // 返回 1
// // cache=[1,2], cnt(2)=1, cnt(1)=2
//lfu.put(3, 3); // 去除键 2 ,因为 cnt(2)=1 ,使用计数最小
// // cache=[3,1], cnt(3)=1, cnt(1)=2
//lfu.get(2); // 返回 -1(未找到)
//lfu.get(3); // 返回 3
// // cache=[3,1], cnt(3)=2, cnt(1)=2
//lfu.put(4, 4); // 去除键 1 ,1 和 3 的 cnt 相同,但 1 最久未使用
// // cache=[4,3], cnt(4)=1, cnt(3)=2
//lfu.get(1); // 返回 -1(未找到)
//lfu.get(3); // 返回 3
// // cache=[3,4], cnt(4)=1, cnt(3)=3
//lfu.get(4); // 返回 4
// // cache=[3,4], cnt(4)=2, cnt(3)=3
//
//
//
// 提示:
//
//
// 0 <= capacity <= 10⁴
// 0 <= key <= 10⁵
// 0 <= value <= 10⁹
// 最多调用 2 * 10⁵ 次 get 和 put 方法
//
// Related Topics 设计 哈希表 链表 双向链表 👍 512 👎 0
import com.sun.org.apache.bcel.internal.generic.RET;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
//leetcode submit region begin(Prohibit modification and deletion)
class LFUCache {
private final int capacity;
private int minFre;
private HashMap<Integer, Integer> keyToFre;
private HashMap<Integer, Integer> keyToVal;
private HashMap<Integer, LinkedHashSet<Integer>> freToKey;
public LFUCache(int capacity) {
this.capacity = capacity;
minFre = 0;
keyToVal = new LinkedHashMap<>();
keyToFre = new LinkedHashMap<>();
freToKey = new LinkedHashMap<>();
}
public int get(int key) {
if (!keyToVal.containsKey(key)) {
return -1;
}
// 更新 fre
increaseFreq(key);
return keyToVal.get(key);
}
public void put(int key, int value) {
if (capacity <= 0) {
return;
}
if (keyToVal.containsKey(key)) {
increaseFreq(key);
keyToVal.put(key, value);
return;
}
if (capacity <= keyToVal.size()) {
removeMinFre();
}
keyToVal.put(key, value);
keyToFre.put(key, 1);
freToKey.putIfAbsent(1, new LinkedHashSet<>());
freToKey.get(1).add(key);
this.minFre = 1;
}
private void increaseFreq(int key) {
Integer fre = keyToFre.get(key);
keyToFre.put(key, fre + 1);
freToKey.get(fre).remove(key);
freToKey.putIfAbsent(fre + 1, new LinkedHashSet<>());
freToKey.get(fre + 1).add(key);
// 若当前 key 使用频率恰好是最小
if (freToKey.get(fre).isEmpty()) {
freToKey.remove(fre);
if (fre == this.minFre) {
this.minFre = fre + 1;
}
}
}
private void removeMinFre() {
LinkedHashSet<Integer> keySet = freToKey.get(this.minFre);
Integer deleteKey = keySet.iterator().next();
keySet.remove(deleteKey);
if (keySet.isEmpty()) {
freToKey.remove(this.minFre);
}
keyToVal.remove(deleteKey);
keyToFre.remove(deleteKey);
}
}
/**
* 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);
*/
//leetcode submit region end(Prohibit modification and deletion)
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
资源推荐
资源详情
资源评论
收起资源包目录
我会在这里存放我的 LeetCode 刷题代码 同时记录我数据结构与算法的学习过程.zip (249个子文件)
.gitignore 176B
.gitignore 176B
.gitignore 132B
.gitignore 132B
[460]LFU 缓存.java 5KB
[990]等式方程的可满足性.java 3KB
[160]相交链表.java 3KB
[752]打开转盘锁.java 3KB
[1094]拼车.java 3KB
[146]LRU 缓存.java 3KB
[51]N 皇后.java 3KB
[496]下一个更大元素 I.java 3KB
[76]最小覆盖子串.java 3KB
[232]用栈实现队列.java 3KB
[450]删除二叉搜索树中的节点.java 3KB
[438]找到字符串中所有字母异位词.java 2KB
[225]用队列实现栈.java 2KB
[322]零钱兑换.java 2KB
[142]环形链表 II.java 2KB
[116]填充每个节点的下一个右侧节点指针.java 2KB
[27]移除元素.java 2KB
[1011]在 D 天内送达包裹的能力.java 2KB
[26]删除有序数组中的重复项.java 2KB
[239]滑动窗口最大值.java 2KB
[1109]航班预订统计.java 2KB
[141]环形链表.java 2KB
[567]字符串的排列.java 2KB
[102]二叉树的层序遍历.java 2KB
[701]二叉搜索树中的插入操作.java 2KB
[111]二叉树的最小深度.java 2KB
[34]在排序数组中查找元素的第一个和最后一个位置.java 2KB
[114]二叉树展开为链表.java 2KB
[875]爱吃香蕉的珂珂.java 2KB
[98]验证二叉搜索树.java 2KB
[300]最长递增子序列.java 2KB
[509]斐波那契数.java 2KB
[503]下一个更大元素 II.java 2KB
[3]无重复字符的最长子串.java 2KB
[876]链表的中间结点.java 1KB
[700]二叉搜索树中的搜索.java 1KB
[19]删除链表的倒数第 N 个结点.java 1KB
[46]全排列.java 1KB
[739]每日温度.java 1KB
[22]括号生成.java 1KB
[704]二分查找.java 1KB
[226]翻转二叉树.java 1KB
[83]删除排序链表中的重复元素.java 1KB
[5]最长回文子串.java 1KB
[53]最大子数组和.java 1KB
[283]移动零.java 1KB
[70]爬楼梯.java 1KB
LeetCode.jpg 5KB
LICENSE 34KB
LeetCode200. 岛屿数量.md 5KB
LeetCode208. 实现 Trie (前缀树).md 5KB
LeetCode212. 单词搜索 II.md 5KB
LeetCode 641. 设计循环双端队列.md 4KB
LeetCode 2. 两数相加.md 4KB
LeetCode123. 买卖股票的最佳时机 III.md 4KB
LeetCode21. 合并两个有序链表.md 4KB
LeetCode36. 有效的数独.md 4KB
LeetCode42. 接雨水.md 4KB
LeetCode289. 生命游戏.md 3KB
LeetCode 8. 字符串转换整数 (atoi).md 3KB
LeetCode30. 串联所有单词的子串.md 3KB
LeetCode334. 递增的三元子序列.md 3KB
LeetCode188. 买卖股票的最佳时机 IV.md 3KB
LeetCode.622. 设计循环队列.md 3KB
LeetCode33. 搜索旋转排序数组.md 3KB
LeetCode37. 解数独.md 3KB
LeetCode 20. 有效的括号.md 3KB
LeetCode300. 最长上升子序列.md 3KB
LeetCode714. 买卖股票的最佳时机含手续费.md 3KB
LeetCode.860柠檬水找零.md 3KB
LeetCode703. 数据流中的第K大元素.md 3KB
LeetCode46. 全排列.md 3KB
LeetCode11. 盛最多水的容器.md 3KB
LeetCode13. 罗马数字转整数.md 3KB
LeetCode229. 求众数 II.md 3KB
LeetCode164. 最大间距.md 3KB
LeetCode5. 最长回文子串.md 3KB
LeetCode48. 旋转图像.md 3KB
LeetCode460. LFU缓存.md 3KB
LeetCode79. 单词搜索.md 3KB
LeetCode51. N皇后.md 3KB
LeetCode4. 寻找两个有序数组的中位数.md 3KB
LeetCode面试题13. 机器人的运动范围.md 2KB
LeetCode. 950 按递增顺序显示卡牌.md 2KB
LeetCode.217存在重复元素.md 2KB
LeetCode49. 字母异位词分组.md 2KB
LeetCode365. 水壶问题.md 2KB
LeetCode10. 正则表达式匹配.md 2KB
LeetCode31. 下一个排列.md 2KB
LeetCode820. 单词的压缩编码.md 2KB
LeetCode778.水位上升的泳池中游泳.md 2KB
LeetCode 239. 滑动窗口最大值.md 2KB
LeetCode695. 岛屿的最大面积.md 2KB
LeetCode 832.翻转图像.md 2KB
LeetCode26.删除排序数组中的重复项.md 2KB
LeetCode1160. 拼写单词.md 2KB
共 249 条
- 1
- 2
- 3
资源评论
极致人生-010
- 粉丝: 4375
- 资源: 3087
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功