大厂常见面试题LRU算法实现

news2024/10/2 14:21:35
  • 要实现put和get的O(1)时间复杂度

  • 最近最少/最久使用问题

  • 将最近最少使用的数据淘汰

  • LRU缓存是操作系统常见的页面缓存淘汰机制

  • 实现方式:哈希表 + 双向链表

    • 哈希表用于存储数据,主要用于实现存取操作put和get的O(1)时间复杂度
    • 双向链表用于记录最近最少使用、最近最久未使用情况,主要是为了实现记录和删除记录操作的O(1)时间复杂度
      • 选择自定义实现双向链表,而不使用自带的双向链表
        • 自定义链表能更好的管控和访问每个节点数据

    算法实现示意图

public class LRUCache {
  // 缓存的最大容量, 存储元素大于这个大小的时候将被优化删除掉
	private int capacity = 0;
  // map,主要用于存储已存储过的数据,以实现访问和添加的O(1)时间复杂度
	private Map<Integer, Node<Integer, Integer>> map = new HashMap<>();
  // 链表的虚拟头结点
	private Node<Integer, Integer> first;
  // 链表的虚拟尾节点
	private Node<Integer, Integer> last;
	
	
	public LRUCache(int capacity) {
		this.capacity = capacity;
		this.first = new Node<>();
		this.last = new Node<>();
		first.next = last;
		last.prev = first;
  }
    
    public int get(int key) {
      // 通过map获取,能实现O(1)时间复杂度
    	Node<Integer, Integer> node = map.get(key);
      // 如果不存在,则直接返回-1
    	if (node == null) return -1;
    	
      // 如果存在,则更新节点位置到头部
    	int v = node.value;
      removeNode(node);
      addAfterFirst(node);
      return v;
    }
    
    public void put(int key, int value) {
    	Node<Integer, Integer> node = map.get(key);
    	if (node != null) {
        // 如果已经存在此节点
        // 就移除当前节点,并在后续通过addAfterFirst方法更新新的元素
    		node.value = value;
    		removeNode(node);
    	} else {
        // 如果不存在此节点,则是新数据
    		if (map.size() == capacity) {
            // 如果当前存储数据已满,则移除链表中最后一个数据
        		removeNode(map.remove(last.prev.key));
        	}
        	
          // map中添加新的数据
        	node = new Node<>(key, value);
        	map.put(key, node);
    	}
    	
      // 添加新的数据到链表头
    	addAfterFirst(node);
    }
    
    // 删除节点
    private void removeNode(Node<Integer, Integer> node) {
    	node.prev.next = node.next;
    	node.next.prev = node.prev;
    }
    
    // 在头部添加节点
    private void addAfterFirst(Node<Integer, Integer> node) {
    	node.next = first.next;
    	first.next.prev = node;
    	node.prev = first;
    	first.next = node;
    }
    
    
    // 自定义链表的节点类
    private class Node<K, V> {
    	public K key;
    	public V value;
    	public Node<K, V> prev;
    	public Node<K, V> next;
    	
    	public Node(K key, V value) {
    		this.key = key;
    		this.value = value;
    	}
    	
    	public Node() {}
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统访问卡顿 慢

Linux系统访问卡顿、慢 1、查看磁盘使用情况2、查看内存使用情况3、查看磁盘IO使用情况4、查看CPU使用情况5、iostat的查询 1、查看磁盘使用情况 [rootlocalhost ~]# df -h 当发现磁盘使用率很高时&#xff0c;那就要释放磁盘空间了&#xff0c;删除一些不必要的文件查看各个目…

03 Linux

第一课 目录 ⼀、进程与线程 1. 进程 2. 线程 3. 进程和线程的使用条件 ⼆、linux下的sudo命令 (1)sudo sudo的功能&#xff1f; sudo提供的临时权限什么时候被取消&#xff1f; (2)为什么要取消 sudo 权限呢&#xff1f; (2)apt sudo apt update 三、linux常⽤…

第10篇:ESP32外部中断功能的使用

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 第3篇:vscode搭建esp32 arduino开发环境 第4篇:vscodeplatformio搭建esp32 arduino开发环境 ​​​​​​第5篇:doit_esp32_devkit_v1使用pmw呼吸灯实验 第6篇:ESP32连接无源喇叭播…

BEVFormer论文解析

背景 跟基于雷达的相比&#xff0c;纯视觉的方案成本低&#xff0c;而且具有RGB和纹理信息&#xff0c;可以用于检测像交通信号灯、车道线等道路要素。 自动驾驶的感知本意是要从多个摄像头给出的2D信息来预测3D bbox(检测)或者semantic map(分割)&#xff0c;最直接的方案是…

PlantUML——类图(持续更新)

前言 在分析代码流程中&#xff0c;我们常常会使用到各种UML图&#xff0c;例如用例图、时序图和类图等&#xff0c;以往使用ProcessOn或亿图图示等工具&#xff0c;但是这些工具难以规范化&#xff0c;有没有一种用代码来生成图形的工具呢&#xff1f; 刚好在出差的晨会中机缘…

神策分析 2.5 上线「经营分析」:可视化分析能力重磅升级!

近日&#xff0c;神策数据发布了全新的神策分析 2.5 版本&#xff0c;该版本以经营分析为主题&#xff0c;支持分析模型与外部数据的融合性接入&#xff0c;构建全域数据融合模型&#xff0c;并提供统一、便捷的指标及可视化能力&#xff0c;实现从用户到经营的全链路、全场景分…

【公网远程手机Android服务器】安卓Termux搭建Web服务器

目录 概述 1.搭建apache 2.安装cpolar内网穿透 3.公网访问配置 4.固定公网地址 5.添加站点 概述 Termux是一个Android终端仿真应用程序&#xff0c;用于在 Android 手机上搭建一个完整的Linux 环境&#xff0c;能够实现Linux下的许多基本操作&#xff0c;不需要root权限…

归并排序 Merge Sort

归并排序的基本思想是什么&#xff1f; 采用分治法&#xff08;Divide and Conquer&#xff09;&#xff0c;递归将待排序的数组平均分成两个子数组&#xff0c;直到子数组长度为 0 或 1&#xff0c;这是 分 Divider。再将排序好的两个子数组合并为一个有序数组&#xff0c;这…

AD学习笔记

1快捷键 A 各种对齐 L 切换顶层底层 右键联合 元器件的锁定 N 连线控制是否显示 2原理图和pcb交叉选择 封装重叠警告 在规则中修改

Tcp协议特点

目录 确认应答&#xff08;ACK&#xff09; 超时重传 建立连接-三次握手 断开连接-四次挥手 Tcp特点主要是分为四点&#xff1a;有连接&#xff0c;可靠传输&#xff0c;面向字节流&#xff0c;全双工。 这里我们主要介绍可靠传输 确认应答&#xff08;ACK&#xff09; …

EasyFalsh移植使用方法

参考&#xff1a;https://blog.csdn.net/Mculover666/article/details/105510837 注意&#xff1a; 这里说的修改默认环境变量后修改环境变量版本号就自动重新写入到flash这句话是有问题的&#xff0c;要开启上面【#define EF_ENV_AUTO_UODATE】宏定义后才会实现该功能&#…

Maven 必备技能:MAC 系统下 JDK和Maven 安装及环境变量配置详细讲解

开发中难免因系统问题或者版本变更反复折腾JDK和Maven环境变量&#xff0c;干脆写个笔记备忘个&#xff0c;也方便小伙伴们节省时间。 JDK安装与环境变量配置 1.官网下载jdk mac安装包: Java Downloads | Oracle " https://www.oracle.com/java/technologies/downloads…

携程网关的架构设计-日流量200亿

一、概述 类似于许多企业的做法&#xff0c;携程 API 网关是伴随着微服务架构一同引入的基础设施&#xff0c;其最初版本于 2014 年发布。随着服务化在公司内的迅速推进&#xff0c;网关逐步成为应用程序暴露在外网的标准解决方案。后续的“ALL IN 无线”、国际化、异地多活等…

【爬虫笔记】Python爬虫简单运用爬取代理IP

一、前言 近些年来&#xff0c;网络上的爬虫越来越多&#xff0c;很多网站都针对爬虫进行了限制&#xff0c;封禁了一些不规则的请求。为了实现正常的网络爬虫任务&#xff0c;爬虫常用代理IP来隐藏自己的真实IP&#xff0c;避免被服务器封禁。本文将介绍如何使用Python爬虫来…

day 1

使用cut截取出Ubuntu用户的家目录&#xff0c;要求&#xff1a;不能使用":"作为分割 grep ^ubuntu /etc/passwd|cut -d / -f 2,3 xmind

芒果app逆向分析 (二)

接着上文,我们发现请求后的结果是加密的状态,我们需要解密成明文看数据。 前面提到无法使用frida,直接上xposed. 直接就hook出来了?? key = "xkSHHy5DQzYwbZS32zJBDyrHCHWMDGDk" iv = "4yXhd2Ta4m6dif54"堆栈记录下,方便后续使用: 调用堆栈:at ja…

网络技术十七:IP路由原理

IP路由原理 引入 路由器负责将数据报文在逻辑网段间进行转发 路由是指导路由器如何进行数据报文发送的路径信息 每台路由器都有路由表&#xff0c;路由存储在路由表中 路由环路是由错误的路由导致的&#xff0c;它会造成IP报文在网络中循环转发&#xff0c;浪费网络带宽 路…

mac项目流程管理 OmniPlan Pro 4中文 for Mac

OmniPlan Pro 4是一款专业的项目管理软件&#xff0c;提供了强大的项目流程管理功能&#xff0c;帮助用户规划、执行和监控项目的各个阶段和任务。 以下是OmniPlan Pro 4中的项目流程管理功能&#xff1a; 1. 项目计划&#xff1a;用户可以使用OmniPlan Pro 4创建项目计划。软…

SAP MM学习笔记27- 购买依赖(采购申请)

前面已经努力的学习了 购买发注&#xff0c;入库&#xff0c;请求书照合 等功能&#xff0c;还是蛮多内容的哈。 剩下的功能&#xff0c;比如 右侧的 所要量决定&#xff0c;供给元决定&#xff0c;仕入先选择 还没学。 从这章开始&#xff0c;要开始学习它们了。 这一章先来…

【案例分享】H3C设备配置端口镜像

简介 本案例介绍本地端口镜像的配置方法。 组网需求 某公司内部各部门使用不同网段的IP地址&#xff0c;其中研发部使用10.1.1.0/24网段&#xff0c;市场部使用12.1.1.0/24网段。现要求通过配置本地端口镜像功能&#xff0c;使用数据监测设备对研发部和市场部访问Internet的流…