首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
热心市民锅锅
西安电子科技大学 Java
发布于广东
关注
已关注
取消关注
@小德同学:
LRU缓存结构
方法:哈希表+双向链表知识点1:哈希表哈希表是一种根据关键码(key)直接访问值(value)的一种数据结构。而这种直接访问意味着只要知道key就能在O(1)O(1)O(1)时间内得到value,因此哈希表常用来统计频率、快速检验某个元素是否出现过等。知识点2:双向链表双向链表是一种特殊的链表,它除了链表具有的每个节点指向后一个节点的指针外,还拥有一个每个节点指向前一个节点的指针,因此它可以任意向前或者向后访问,每次更改节点连接状态的时候,需要变动两个指针。思路:插入与访问值都是O(1)O(1)O(1),没有任何一种数据结构可以直接做到。于是我们可以想到数据结构的组合:访问O(1)O(1)O(1)很容易想到了哈希表;插入O(1)O(1)O(1)的数据结构有很多,但是如果访问到了这个地方再选择插入,且超出长度要在O(1)O(1)O(1)之内删除,我们可以想到用链表,可以用哈希表的key值对应链表的节点,完成直接访问。但是我们还需要把每次访问的key值节点加入链表头,同时删掉链表尾,所以选择双向链表,便于删除与移动。于是我们的方法就是哈希表+双向链表。具体做法:step 1:构建一个双向链表的类,记录key值与val值,同时一前一后两个指针。用哈希表存储key值和链表节点,这样我们可以根据key值在哈希表中直接锁定链表节点,从而实现在链表中直接访问,能够做到O(1)O(1)O(1)时间访问链表任意节点。 //设置双向链表结构 class Node{ int key; int val; Node pre; Node next; //初始化 public Node(int key, int val) { this.key = key; this.val = val; this.pre = null; this.next = null; } }step 2:设置全局变量,记录双向链表的头、尾及LRU剩余的大小,并全部初始化,首尾相互连接好。//构建初始化连接//链表剩余大小this.size = k;this.head.next = this.tail;this.tail.pre = this.head;step 3:遍历函数的操作数组,检查第一个元素判断是属于set操作还是get操作。step 4:如果是set操作,即将key值与val值加入链表,我们先检查链表中是否有这个key值,可以通过哈希表检查出,如果有直接通过哈希表访问链表的相应节点,修改val值,并将访问过的节点移到表头;如果没有则需要新建节点加到表头,同时哈希表中增加相应key值(当然,还需要检查链表长度还有无剩余,若是没有剩余则需要删去链表尾)。//没有见过这个key,新值加入if(!mp.containsKey(key)){ Node node = new Node(key, val); mp.put(key, node); //超出大小,移除最后一个 if(size <= 0) removeLast(); //大小还有剩余 else //大小减1 size--; //加到链表头 insertFirst(node); }//哈希表中已经有了,即链表里也已经有了else{ mp.get(key).val = val; //访问过后,移到表头 moveToHead(mp.get(key)); }step 5:不管是新节点,还是访问过的节点都需要加到表头,若是访问过的,需要断开原来的连接,再插入表头head的后面。//移到表头函数void moveToHead(Node node){ //已经到了表头 if(node.pre == head) return; //将节点断开,取出来 node.pre.next = node.next; node.next.pre = node.pre; //插入第一个前面 insertFirst(node);}step 6:删除链表尾需要断掉尾节点前的连接,同时哈希表中去掉这个key值。void removeLast(){ //哈希表去掉key mp.remove(tail.pre.key); //断连该节点 tail.pre.pre.next = tail; tail.pre = tail.pre.pre;}step 7:如果是get操作,检验哈希表中有无这个key值,如果没有说明链表中也没有,返回-1,否则可以根据哈希表直接锁定链表中的位置进行访问,然后重复step 5,访问过的节点加入表头。if(mp.containsKey(key)){ Node node = mp.get(key); res = node.val; moveToHead(node);}图示:Java代码实现:import java.util.*;public class Solution { //设置双向链表结构 static class Node{ int key; int val; Node pre; Node next; //初始化 public Node(int key, int val) { this.key = key; this.val = val; this.pre = null; this.next = null; } } //哈希表 private Map<Integer, Node> mp = new HashMap<>(); //设置一个头 private Node head = new Node(-1, -1); //设置一个尾 private Node tail = new Node(-1, -1); private int size = 0; public int[] LRU (int[][] operators, int k) { //构建初始化连接 //链表剩余大小 this.size = k; this.head.next = this.tail; this.tail.pre = this.head; //获取操作数 int len = (int)Arrays.stream(operators).filter(x -> x[0] == 2).count(); int[] res = new int[len]; //遍历所有操作 for(int i = 0, j = 0; i < operators.length; i++){ if(operators[i][0] == 1) //set操作 set(operators[i][1], operators[i][2]); else //get操作 res[j++] = get(operators[i][1]); } return res; } //插入函数 private void set(int key, int val){ //没有见过这个key,新值加入 if(!mp.containsKey(key)){ Node node = new Node(key, val); mp.put(key, node); //超出大小,移除最后一个 if(size <= 0) removeLast(); //大小还有剩余 else //大小减1 size--; //加到链表头 insertFirst(node); } //哈希表中已经有了,即链表里也已经有了 else{ mp.get(key).val = val; //访问过后,移到表头 moveToHead(mp.get(key)); } } //获取数据函数 private int get(int key){ int res = -1; if(mp.containsKey(key)){ Node node = mp.get(key); res = node.val; moveToHead(node); } return res; } //移到表头函数 private void moveToHead(Node node){ //已经到了表头 if(node.pre == head) return; //将节点断开,取出来 node.pre.next = node.next; node.next.pre = node.pre; //插入第一个前面 insertFirst(node); } //将节点插入表头函数 private void insertFirst(Node node){ node.pre = head; node.next = head.next; head.next.pre = node; head.next = node; } //删去表尾函数,最近最少使用 private void removeLast(){ //哈希表去掉key mp.remove(tail.pre.key); //断连该节点 tail.pre.pre.next = tail; tail.pre = tail.pre.pre; }}
点赞 0
评论 0
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
昨天 17:54
门头沟学院 营销
什么时候能和mt这么说话
看到这图有的时候我也想发挥一下我的幽默天赋但是怕被我的mt真实
驼瑞驰_招募评论官版...:
刘总:以后你是刘总
点赞
评论
收藏
分享
08-08 15:40
已编辑
中南大学
AI是不是要把线上面试毁了?
这两天还琢磨着给学弟学妹推一个还不错的公司,一问朋友说公司招聘线上面试作弊的太多了,全改线下了.....我这好奇直接问北京这么远没多少人能去呀结果回复是:老板说人多的是只招北京的就够了,线上招聘过两个作弊通过的到公司,啥也不会,给团队搞得头疼。#牛客AI配图神器#
爱睡觉的冰箱哥:
要是线下面,不是北上的学校真的麻烦死了
点赞
评论
收藏
分享
07-17 12:05
已编辑
快手_KSIB_java后台(实习员工)
后端暑期第一个offer!
收到京东的意向书,实习5个多月了,也该撤退了,可以安心做毕设,备战秋招了
点赞
评论
收藏
分享
06-28 22:48
已编辑
广东金融学院 Java
大三双非本点评➕外卖连面试都没有
有没有大佬指点,真的失业了😭
小浪_Coding:
学院本+这俩项目不是buff叠满了嘛
点赞
评论
收藏
分享
08-06 10:51
门头沟学院 硬件开发
今天面试小公司
找找面试的感觉,秋招加油
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
25年秋招精心整理的最新互联网大厂笔面试题集合
2.4W
2
...
26秋招-拓竹嵌入式软件面经
3512
3
...
重生之我在牛客写简历。
2965
4
...
暑期实习转正自评,你就这么写!
2944
5
...
字节意向
2886
6
...
唯品会Java一二面
2614
7
...
字节秋招意向
2614
8
...
今天中午恍惚了好一阵子
2568
9
...
影石嵌入式驱动开发面经
2183
10
...
亚信科技java实习面经
1963
创作者周榜
更多
正在热议
更多
#
实习的内耗时刻
#
7696次浏览
110人参与
#
每个月的工资都是怎么分配的?
#
57859次浏览
560人参与
#
去哪儿旅行秋招
#
220247次浏览
3153人参与
#
你上一次给父母打电话是什么时候
#
3270次浏览
39人参与
#
独居后,你的生活是更好了还是更差了?
#
2595次浏览
43人参与
#
规定下班时间vs实际下班时间
#
5520次浏览
50人参与
#
腾讯大前端岗位热招中
#
12925次浏览
132人参与
#
工作上你捅过哪些篓子?
#
4105次浏览
30人参与
#
视觉/交互/设计百问百答
#
52417次浏览
442人参与
#
你觉得材料多少算高薪
#
21964次浏览
148人参与
#
秋招笔面试记录
#
88446次浏览
1705人参与
#
央国企投递记录
#
98323次浏览
1408人参与
#
美团秋招笔试
#
61230次浏览
401人参与
#
入职第二天,午饭怎么解决
#
26129次浏览
74人参与
#
tplink提前批进度交流
#
194977次浏览
1477人参与
#
2023毕业生求职有问必答
#
186695次浏览
1629人参与
#
你们公司哪个部门最累?
#
29697次浏览
213人参与
#
找工作有哪些冷知识
#
137734次浏览
2337人参与
#
牛友们的论文几号送审
#
49881次浏览
797人参与
#
今年形式下双非本找得到工作吗
#
207075次浏览
1278人参与
#
你觉得现在还能进互联网吗?
#
20487次浏览
186人参与
#
得物求职进展汇总
#
103423次浏览
826人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务