一道很考验数据结构与算法的功底的笔试题:用JAVA设计一个缓存结构
我在上周的笔试中遇到了这样一道题目,觉得有难度而且很考验数据结构与算法的功底,因此Mark一下。
需求说明
设计并实现一个缓存数据结构:
 该数据结构具有以下功能:
 get(key)
 如果指定的key存在于缓存中,则返回与该键关联的值,则返回-1。
 put(key、val、weight)
 将值与缓存中的键关联,以便以后可以通过get(key)检索值。
 缓存具有固定的容量,当达到该容量时,score最小的密钥必须失效,直到密钥的数量落在缓存容量之内。
 score的计算方法如下:
 weight ∕ [ln(current_time - last_accessed_time + 1) + 1]
 缓存的实现需要get(key)的时间复杂度为O(1)。为了实现高速缓存,您可以假设可用一些常见的数据结构,如数组、不同类型的列表和哈希表。在答案的最后,给出并解释get(key)和放入put(key)的计算复杂度
我的思路
首先,一说到get和put,肯定会想到哈希map,并且哈希的get时间复杂度也为O(1),符合要求,但比较棘手的需求是如何实现缓存的score机制,当缓存满的时候需要让score最低的节点drop掉。苦思冥想之后我想到了优先队列(priority queue),平时觉得这个数据结构很冷门,但确实有应用场景,优先队列是一种根据权重进行出队顺序排列的队列,那么我只需要将题目中的score定位为权重就行了。
 此时我又想到了用JAVA中的Comparator去定义一个这样的权重策略,因为优先队列的权重是可以被Comparator重写的。所以我总共需要用到两个数据结构。
 用hashmap实现get和put的一一对应,同时将节点存入优先队列,当容量满时让score小的出队就行了。(注意,Java中优先队列是权重小的先出队)
我的答案
import java.util.*;class Node{int key;int val;int weight;int timeStamp;public Node(int key, int val, int weight, int timeStamp) {this.key = key;this.val = val;this.weight = weight;this.timeStamp = timeStamp;}
}public class Cache {int capacity;int timeStamp;Map<Integer,Node> nodeMap;  //k-v mappingPriorityQueue<Node> prque;  //store the nodepublic Cache(int capacity){this.capacity = capacity;this.timeStamp = 0;nodeMap = new HashMap<>();Comparator<Node> timeWeightComparator = new Comparator<Node>() { //rewrite the priority@Overridepublic int compare(Node o1, Node o2) {return (int) (o1.weight / (Math.log(o1.timeStamp - o2.timeStamp + 1) + 1) -(o2.weight / (Math.log(o2.timeStamp - o1.timeStamp + 1) + 1)));}};prque = new PriorityQueue<>(timeWeightComparator);}public int get(int key){  //时间复杂度O(1), hashmap.get为O(1)if (!nodeMap.containsKey(key)){return -1;}Node getNode = nodeMap.get(key);getNode.timeStamp = ++timeStamp;return getNode.val;}void put(int key, int val, int weight){ //最好的情况是已经包含这个键了,时间复杂度为O(1)if (this.capacity <= 0){return;}if (nodeMap.containsKey(key)){Node newNode = nodeMap.get(key);newNode.val = val;newNode.weight = weight;newNode.timeStamp = ++ timeStamp;}else {if (nodeMap.size() == capacity){Node leastNode = prque.poll(); //O(logN)assert leastNode != null;nodeMap.remove(leastNode.key);}Node newNode = new Node(key, val, weight, ++timeStamp);prque.add(newNode);nodeMap.put(key,newNode);}}public static void main(String[] args) { //test caseCache cache = new Cache(5);cache.put(0,15,3);cache.put(1,28,10);cache.put(2,16,4);cache.put(3,4,6);cache.put(4,75,5);cache.put(4,100,100);System.out.println(cache.get(1));System.out.println(cache.get(2));System.out.println(cache.get(3));System.out.println(cache.get(4));System.out.println(cache.get(0));}
}
BigO notation analysis
get
The get operation is base on the hashmap.get(key). So, the time complexity is O(1).
put
The put operation can be seperated to follow two case:
1. Don’t need insert a new node (when the key is exist)
In this case, we only need to get the node from hashmap and update it. The time complexity is O(1).
2. Insert new Node
If the capcity is not reached. we can insert a new node directly. the complexity is O(logN) + O(1) = O(logN) ---- (O(logN) for priorityque, O(1) for hashmap).
If the capicity is reached. we need to poll a node with least score, the time complexity is O(logN). Then inster a new node. The time complexity is O(logN) + O(logN) + O(1) = O(logN).
相关文章:
一道很考验数据结构与算法的功底的笔试题:用JAVA设计一个缓存结构
我在上周的笔试中遇到了这样一道题目,觉得有难度而且很考验数据结构与算法的功底,因此Mark一下。 需求说明 设计并实现一个缓存数据结构: 该数据结构具有以下功能: get(key) 如果指定的key存在于缓存中,则返回与该键关联的值&am…...
(10)C#传智:命名空间、String/StringBuilder、指针、继承New(第10天)
内容开始多了,慢品慢尝才有滋味。 一、命名空间namespace 用于解决类重名问题,可以看作类的文件夹. 若代码与被使用的类,与当前的namespace相同,则不需要using. 若namespace不同时,调用的方法:…...
 
基于Jetson Tx2 Nx的Qt、树莓派等ARM64架构的Ptorch及torchvision的安装
前提 已经安装好了python、pip及最基本的依赖库 若未安装好点击python及pip安装请参考这篇博文 https://blog.csdn.net/m0_51683386/article/details/129320492?spm1001.2014.3001.5502 特别提醒 一定要先根据自己板子情况,找好python、torch、torchvision的安…...
 
MySQL存储引擎详解及对比和选择
什么是存储引擎? MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善…...
 
【推拉框-手风琴】vue3实现手风琴效果的组件
简言 在工作时有时会用到竖形手风琴效果的组件。 在此记录下实现代码和实现思路。 手风琴实现 结构搭建 搭建结构主要实现盒子间的排列效果。 用flex布局或者其他布局方式将内容在一行排列把每一项的内容和项头用盒子包裹, 内容就是这一项要展示的内容…...
 
滑动窗口最大值:单调队列
239. 滑动窗口最大值 难度困难2154收藏分享切换为英文接收动态反馈 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例…...
负载均衡算法
静态负载均衡 轮询 将请求按顺序轮流地分配到每个节点上,不关心每个节点实际的连接数和当前的系统负载。 优点:简单高效,易于水平扩展,每个节点满足字面意义上的均衡; 缺点:没有考虑机器的性能问题&…...
 
C语言数组二维数组
C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量,比如 runoob0、runoob1、…、runoob99,而是…...
 
7年测试工程师,裸辞掉17K的工作,想跳槽找更好的,还是太高估自己了....
14年大学毕业后,在老师和朋友的推荐下,进了软件测试行业,这一干就是7年时间,当时大学本来就是计算机专业,虽然专业学的一塌糊涂,但是当年的软件测试属于新兴行业,人才缺口比较大,而且…...
 
企业为什么需要做APP安全评估?
近几年新型信息基础设施建设和移动互联网技术的不断发展,移动APP数量也呈现爆发式增长,进而APP自身的“脆弱性”也日益彰显,这对移动用户的个人信息及财产安全带来巨大威胁和挑战。在此背景下,国家出台了多部法律法规,…...
 
重回利润增长,涪陵榨菜为何能跑赢周期?
2022年消费市场持续低迷,疫情寒冬之下,不少食品快消企业均遭遇严重的业绩下滑,但一年里不断遭遇利空打击的“榨菜茅”涪陵榨菜,不仅安然躲过“酸菜劫”、走出“钠”争议,而且顺利将产品价格提起来,并在寒冬…...
 
这6个高清图片素材库,马住,马住~
网上找的图片素材清晰度不够,版权不明确怎么办。看看这几个可商用图片素材网站,解决你的所有图片需求,高清无水印,赶紧马住! 1、菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片素材下载网 - 菜鸟图库  网站素材…...
绝对零基础的C语言科班作业(期末模拟考试)
编程题(共10题; 共100.0分)模拟1(输出m到n的素数)从键盘输入两个整数[m,n], 输出m和n之间的所有素数。 输入样例:3,20输出样例:3 5 7 11 13 17 19 (输出数据之间用空格间…...
 
注解开发定义bean
注解开发定义bean 使用Component定义bean在核心配置文件中通过组件扫描加载bean,需要指定扫描包的范围 当然也可以使用Component的衍生注解,可以更加形象的表示 纯注解的开发模式 使用java类来代替了以前的 配置文件,在java类中ÿ…...
剑指 Offer 19. 正则表达式匹配
摘要 剑指 Offer 19. 正则表达式匹配 请实现一个函数用来匹配包含. 和*的正则表达式。模式中的字符.表示任意一个字符,而*表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如&#x…...
 
CSS——学成在线案例
🍓个人主页:bit.. 🍒系列专栏:Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 HTML和CSS3 目录 1.案例准备工作 2.CSS属性书写顺序(重点) 3.页面布局整体思路 4.头部的制作编辑 5.banner制作…...
元数据的类型
元数据通常分为三种类型:业务元数据、技术元数据和操作元数据。这些类别使人们能够理解属于元数据总体框架下的信息范围,以及元数据的产生过程。也就是说,这些类别也可能导致混淆,特别是当人们对一组元数据属于哪个类别或应该由谁…...
 
LEAP模型的能源环境发展、碳排放建模预测及不确定性分析
LEAP(Long Range Energy Alternatives Planning System/ Low emission analysis platform,长期能源可替代规划模型)是一种自下而上的能源-环境核算工具,由斯德哥尔摩环境研究所和美国波士顿大学联合研发。该模型与情景分析法紧密结…...
C# Task详解
1、Task产生背景 Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然也可以基本业务需要的多线程场景,但它们在多个线程的等待处理方面、资源占用方面、线程延续和阻塞方面、线程的取消方面等都显得比…...
Blob分析+特征
Blob分析特征0 前言1 概念2 方法2.1 图像采集2.2 图像分割2.3 特征提取3 主要应用场景:0 前言 在缺陷检测领域,halcon通常有6种处理方法,包括Blob分析特征、Blob分析特征差分、频域空间域、光度立体法、特征训练、测量拟合,本篇博…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
 
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
 
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
 
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
 
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
 
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
 
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
