力扣算法题—460LFU缓存
【题目描述】
设计并实现最不经常使用(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
【解题思路】
解题思路见我博客:左神算法进阶班6_1LFU缓存实现
【代码实现】
#pragma once
#include <iostream>
#include <map> using namespace std; class LFUCache {
public:
LFUCache(int capacity) {
this->capacity = capacity;
} int get(int key) {
if (dataMap.find(key) == dataMap.end())//数据不存在
return -;
Node* p = dataMap[key];//找到数据节点
NodeList* h = headMap[p->num];
updataNode(p, h); return p->val;
} void put(int key, int value) {
if (capacity == )
return;
if (dataMap.find(key) != dataMap.end())//已经存在
{
Node* p = dataMap[key];//找到数据节点
NodeList* h = headMap[p->num];//找到头链表节点
p->val = value; updataNode(p, h);//更新数据的使用次数
}
else//如果不存在,则新建
{
if (dataMap.size() >= this->capacity)//容量不足,需要删除数据
deleteData(); Node* p = new Node(key, value, );//使用用一次
dataMap[key] = p;//记录 //将新建节点插入使用1次的子链表中
if (headMap.find() == headMap.end())//当使用1次的子链表不存在
createNode(p, headList);
else
moveNode(p, headMap[]);//插入在使用次数在1的子链表中
}
} private:
struct Node//子链表
{
int key;
int val;
int num;
Node* next;
Node* pre;
Node(int a, int b, int n) :key(a), val(b), num(n), next(nullptr), pre(nullptr) {}
}; struct NodeList//主链表
{
int num;
Node* head;//子链表的头节点
Node* tail;//子链表的尾结点
NodeList* next;
NodeList* pre;
NodeList(int a) :num(a), next(nullptr), pre(nullptr)
{
head = new Node(, , a);//新建一个子链表的头结点
tail = head;
}
}; private:
void getNode(Node*& p, NodeList*& h)//将节点从子链表中取出
{
p->pre->next = p->next;
if (p->next == nullptr)
h->tail = p->pre;
else
p->next->pre = p->pre;
}
void moveNode(Node*& p, NodeList*& q)//将节点向后移动
{
p->next = q->tail->next;
q->tail->next = p;
p->pre = q->tail;
q->tail = p;
}
void deleteNode(int num, NodeList*& h)//删除子链表
{
headMap.erase(num);//从map中删除
h->pre->next = h->next;
if (h->next != nullptr)
h->next->pre = h->pre;
delete h;
h = nullptr;
}
void createNode(Node*p, NodeList*& h)//新建子链表,并插入在主链中
{
NodeList* q = new NodeList(p->num);//新建一个子链表
headMap[p->num] = q;//保存对应的地址 moveNode(p, q);////将节点放入子链表中 //将新子链插入主链表中
q->next = h->next;
if (h->next != nullptr)
h->next->pre = q;
h->next = q;
q->pre = h;
}
void updataNode(Node*& p, NodeList*& h)//更新函数的使用次数
{
int num = p->num;
p->num++;//使用次数+1 //将p从子链表中取出
getNode(p, h); //将该数据向后面移动
if (headMap.find(p->num) == headMap.end())//不存在num+1的节点,那么新建
createNode(p, h);
else
moveNode(p, headMap[p->num]);////将节点放入子链表中 //如果该子链表为空,将该子链表删除,并从map中删除
if (h->head == h->tail)
deleteNode(num, h);
}
void deleteData()//容量不足需要删除
{
NodeList* p = headList->next;
Node* q = p->head->next;//删除子链表排在最前面的数据
if (q == p->tail)//要删除的数据就是最后一个数据,则删除该节点和子链表
deleteNode(q->num, p);
else
{
p->head->next = q->next;
q->next->pre = p->head;
}
dataMap.erase(q->key);//删除记录
delete q;//删除
q = nullptr;
} private:
int capacity;
NodeList* headList = new NodeList();//主链表的头结点
map<int, Node*>dataMap;//key <——> 真实数据节点地址
map<int, NodeList*>headMap;//次数 <——> 链表头节点地址
}; /**
* 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);
*/ void Test()
{
LFUCache* f = new LFUCache();
f->put(, );
f->put(, );
f->put(, );
f->put(, );
cout << f->get() << endl;
cout << f->get() << endl;
cout << f->get() << endl;
cout << f->get() << endl;
f->put(, );
cout << f->get() << endl;
cout << f->get() << endl;
cout << f->get() << endl;
cout << f->get() << endl;
cout << f->get() << endl; }
力扣算法题—460LFU缓存的更多相关文章
- 力扣算法题—146LRU缓存机制
[题目] 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (k ...
- 力扣算法题—069x的平方根
实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 输出: 2 示例 ...
- 力扣算法题—060第K个排列
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: "123" "132&qu ...
- 力扣算法题—050计算pow(x, n)
#include "000库函数.h" //使用折半算法 牛逼算法 class Solution { public: double myPow(double x, int n) { ...
- 力扣算法题—147Insertion_Sort_List
Sort a linked list using insertion sort. A graphical example of insertion sort. The partial sorted l ...
- 力扣算法题—093复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135", ...
- 力扣算法题—079单词搜索【DFS】
给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被重复使用. ...
- 力扣算法题—052N皇后问题2
跟前面的N皇后问题没区别,还更简单 #include "000库函数.h" //使用回溯法 class Solution { public: int totalNQueens(in ...
- 力扣算法题—051N皇后问题
#include "000库函数.h" //使用回溯法来计算 //经典解法为回溯递归,一层一层的向下扫描,需要用到一个pos数组, //其中pos[i]表示第i行皇后的位置,初始化 ...
随机推荐
- drools决策表的使用
决策表我们在drools规则引擎初探里做了简单介绍,这里主要是介绍如何通过java代码来把这个excel文件和drools关联起来,如何使其达到我们想要的效果. 这里假设我们在resources目录下 ...
- JS函数 返回值的函数 return sum;或者result = add2(3,4);
返回值的函数 思考:上一节函数中,通过"document.write"把结果输出来,如果想对函数的结果进行处理怎么办呢? 我们只要把"document.write(sum ...
- Got permission denied while trying to connect to the Docker daemon
答案:https://stackoverflow.com/questions/48568172/docker-sock-permission-denied
- CSIC_716_20191028【爬小破站】
1.爬取小破站的弹幕 2.展示爬取内容 打开网页,用教的方法找到cid 和header import requests from bs4 import BeautufulSoup import pan ...
- 为什么串行传输时总是LSB在前?
https://superuser.com/questions/1104212/why-do-serial-ports-send-data-least-significant-bit-first 其实 ...
- java 选择结构if
图1-1 if…else if…else语句的流程图 选择结构if语句与三元运算转换 三元运算符,它和if-else语句类似,语法如下: 判断条件 ? 表达式1 : 表达式2 三元运算符会得 ...
- Windows ping
用法: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS] [-r count] [-s count] [[-j ...
- JSONObject 序列化后,对象数据为引用地址
最近在json序列化的时候,遇到了个坑,记录如下: public static void main(String[] args) { JSONObject json = new JSONObject( ...
- echarts折线区域图
一.使用场景 当舒张压和收缩压超过或低于他们对应的范围时,折线应该给与不同颜色.两个指标对应的范围也要填充不同的颜色. 二.实现方案 主要使用了echarts中的visualMap,series.ma ...
- (转)Java ClassLoader详解
转:http://java.chinaitlab.com/base/804400.html 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态 ...