当前位置: 首页 > news >正文

一道很考验数据结构与算法的功底的笔试题:用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设计一个缓存结构

我在上周的笔试中遇到了这样一道题目&#xff0c;觉得有难度而且很考验数据结构与算法的功底&#xff0c;因此Mark一下。 需求说明 设计并实现一个缓存数据结构: 该数据结构具有以下功能&#xff1a; get(key) 如果指定的key存在于缓存中&#xff0c;则返回与该键关联的值&am…...

(10)C#传智:命名空间、String/StringBuilder、指针、继承New(第10天)

内容开始多了&#xff0c;慢品慢尝才有滋味。 一、命名空间namespace 用于解决类重名问题&#xff0c;可以看作类的文件夹. 若代码与被使用的类&#xff0c;与当前的namespace相同&#xff0c;则不需要using. 若namespace不同时&#xff0c;调用的方法&#xff1a…...

基于Jetson Tx2 Nx的Qt、树莓派等ARM64架构的Ptorch及torchvision的安装

前提 已经安装好了python、pip及最基本的依赖库 若未安装好点击python及pip安装请参考这篇博文 https://blog.csdn.net/m0_51683386/article/details/129320492?spm1001.2014.3001.5502 特别提醒 一定要先根据自己板子情况&#xff0c;找好python、torch、torchvision的安…...

MySQL存储引擎详解及对比和选择

什么是存储引擎&#xff1f; MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术&#xff0c;你能够获得额外的速度或者功能&#xff0c;从而改善…...

【推拉框-手风琴】vue3实现手风琴效果的组件

简言 在工作时有时会用到竖形手风琴效果的组件。 在此记录下实现代码和实现思路。 手风琴实现 结构搭建 搭建结构主要实现盒子间的排列效果。 用flex布局或者其他布局方式将内容在一行排列把每一项的内容和项头用盒子包裹&#xff0c; 内容就是这一项要展示的内容&#xf…...

滑动窗口最大值:单调队列

239. 滑动窗口最大值 难度困难2154收藏分享切换为英文接收动态反馈 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例…...

负载均衡算法

静态负载均衡 轮询 将请求按顺序轮流地分配到每个节点上&#xff0c;不关心每个节点实际的连接数和当前的系统负载。 优点&#xff1a;简单高效&#xff0c;易于水平扩展&#xff0c;每个节点满足字面意义上的均衡&#xff1b; 缺点&#xff1a;没有考虑机器的性能问题&…...

C语言数组二维数组

C 语言支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 runoob0、runoob1、…、runoob99&#xff0c;而是…...

7年测试工程师,裸辞掉17K的工作,想跳槽找更好的,还是太高估自己了....

14年大学毕业后&#xff0c;在老师和朋友的推荐下&#xff0c;进了软件测试行业&#xff0c;这一干就是7年时间&#xff0c;当时大学本来就是计算机专业&#xff0c;虽然专业学的一塌糊涂&#xff0c;但是当年的软件测试属于新兴行业&#xff0c;人才缺口比较大&#xff0c;而且…...

企业为什么需要做APP安全评估?

近几年新型信息基础设施建设和移动互联网技术的不断发展&#xff0c;移动APP数量也呈现爆发式增长&#xff0c;进而APP自身的“脆弱性”也日益彰显&#xff0c;这对移动用户的个人信息及财产安全带来巨大威胁和挑战。在此背景下&#xff0c;国家出台了多部法律法规&#xff0c;…...

重回利润增长,涪陵榨菜为何能跑赢周期?

2022年消费市场持续低迷&#xff0c;疫情寒冬之下&#xff0c;不少食品快消企业均遭遇严重的业绩下滑&#xff0c;但一年里不断遭遇利空打击的“榨菜茅”涪陵榨菜&#xff0c;不仅安然躲过“酸菜劫”、走出“钠”争议&#xff0c;而且顺利将产品价格提起来&#xff0c;并在寒冬…...

这6个高清图片素材库,马住,马住~

网上找的图片素材清晰度不够&#xff0c;版权不明确怎么办。看看这几个可商用图片素材网站&#xff0c;解决你的所有图片需求&#xff0c;高清无水印&#xff0c;赶紧马住&#xff01; 1、菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片素材下载网 - 菜鸟图库 ​ 网站素材…...

绝对零基础的C语言科班作业(期末模拟考试)

编程题&#xff08;共10题&#xff1b; 共100.0分&#xff09;模拟1&#xff08;输出m到n的素数&#xff09;从键盘输入两个整数[m,n], 输出m和n之间的所有素数。 输入样例&#xff1a;3&#xff0c;20输出样例&#xff1a;3 5 7 11 13 17 19 &#xff08;输出数据之间用空格间…...

注解开发定义bean

注解开发定义bean 使用Component定义bean在核心配置文件中通过组件扫描加载bean&#xff0c;需要指定扫描包的范围 当然也可以使用Component的衍生注解&#xff0c;可以更加形象的表示 纯注解的开发模式 使用java类来代替了以前的 配置文件&#xff0c;在java类中&#xff…...

剑指 Offer 19. 正则表达式匹配

摘要 剑指 Offer 19. 正则表达式匹配 请实现一个函数用来匹配包含. 和*的正则表达式。模式中的字符.表示任意一个字符&#xff0c;而*表示它前面的字符可以出现任意次&#xff08;含0次&#xff09;。在本题中&#xff0c;匹配是指字符串的所有字符匹配整个模式。例如&#x…...

CSS——学成在线案例

&#x1f353;个人主页&#xff1a;bit.. &#x1f352;系列专栏&#xff1a;Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 HTML和CSS3 目录 1.案例准备工作 2.CSS属性书写顺序&#xff08;重点&#xff09; 3.页面布局整体思路 4.头部的制作​编辑 5.banner制作…...

元数据的类型

元数据通常分为三种类型&#xff1a;业务元数据、技术元数据和操作元数据。这些类别使人们能够理解属于元数据总体框架下的信息范围&#xff0c;以及元数据的产生过程。也就是说&#xff0c;这些类别也可能导致混淆&#xff0c;特别是当人们对一组元数据属于哪个类别或应该由谁…...

LEAP模型的能源环境发展、碳排放建模预测及不确定性分析

LEAP&#xff08;Long Range Energy Alternatives Planning System/ Low emission analysis platform&#xff0c;长期能源可替代规划模型&#xff09;是一种自下而上的能源-环境核算工具&#xff0c;由斯德哥尔摩环境研究所和美国波士顿大学联合研发。该模型与情景分析法紧密结…...

C# Task详解

1、Task产生背景 Task出现之前&#xff0c;微软的多线程处理方式有&#xff1a;Thread→ThreadPool→委托的异步调用&#xff0c;虽然也可以基本业务需要的多线程场景&#xff0c;但它们在多个线程的等待处理方面、资源占用方面、线程延续和阻塞方面、线程的取消方面等都显得比…...

Blob分析+特征

Blob分析特征0 前言1 概念2 方法2.1 图像采集2.2 图像分割2.3 特征提取3 主要应用场景&#xff1a;0 前言 在缺陷检测领域&#xff0c;halcon通常有6种处理方法&#xff0c;包括Blob分析特征、Blob分析特征差分、频域空间域、光度立体法、特征训练、测量拟合&#xff0c;本篇博…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...