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

Python算法题集_LRU 缓存

 Python算法题集_LRU 缓存

  • 题146:LRU 缓存
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【队列+字典】
    • 2) 改进版一【有序字典】
    • 3) 改进版二【双向链表+字典】
  • 4. 最优算法

本文为Python算法题集之一的代码示例

题146:LRU 缓存

1. 示例说明

  • 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

    实现 LRUCache 类:

    • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
    • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
    • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

    函数 getput 必须以 O(1) 的平均时间复杂度运行。

    示例:

    输入
    ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
    [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
    输出
    [null, null, null, 1, null, -1, null, -1, 3, 4]解释
    LRUCache lRUCache = new LRUCache(2);
    lRUCache.put(1, 1); // 缓存是 {1=1}
    lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
    lRUCache.get(1);    // 返回 1
    lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
    lRUCache.get(2);    // 返回 -1 (未找到)
    lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
    lRUCache.get(1);    // 返回 -1 (未找到)
    lRUCache.get(3);    // 返回 3
    lRUCache.get(4);    // 返回 4
    

    提示:

    • 1 <= capacity <= 3000
    • 0 <= key <= 10000
    • 0 <= value <= 105
    • 最多调用 2 * 105getput

2. 题目解析

- 题意分解

  1. 本题为设计一个整形缓存类,可以指定缓存大小
  2. 基本的设计思路是采用队列控制使用次序,字典进行缓存【哈希】

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以考虑采用有序字典设计缓存类

    2. 可以考虑采用双向链表设计使用队列,缓存还是采用字典


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【队列+字典】

队列控制使用次序,字典保存键值对

勉强通关,超过05%在这里插入图片描述

import CheckFuncPerf as cfpclass LRUCache_base:
def __init__(self, capacity):self.queue, self.dict, self.capacity, self.queuelen = [], {}, capacity, 0
def get(self, key):if key in self.queue:self.queue.remove(key)self.queue.append(key)return self.dict[key]else:return -1
def put(self, key, value):if key in self.queue:self.queue.remove(key)else:if self.queuelen == self.capacity:self.dict.pop(self.queue.pop(0))else:self.queuelen += 1self.queue.append(key)self.dict[key] = valutmpLRUCache = LRUCache_base(5)
result = cfp.getTimeMemoryStr(testLRUCache, tmpLRUCache, actions)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 testLRUCache 的运行时间为 561.12 ms;内存使用量为 4.00 KB 执行结果 = 99

2) 改进版一【有序字典】

采用有序字典【Python3.6之后支持】,同时支持使用顺序和保存键值对

性能卓越,超越93%在这里插入图片描述

import CheckFuncPerf as cfpclass LRUCache_ext1:def __init__(self, capacity):self.data = dict()self.capacity = capacitydef get(self, key):keyval = self.data.get(key, -1)if keyval != -1:self.data.pop(key)self.data[key] = keyvalreturn keyvaldef put(self, key, value)if key in self.data:self.data.pop(key)self.data[key] = valueelse:if len(self.data) < self.capacity:self.data[key] = valueelse:firstpop = next(iter(self.data))self.data.pop(firstpop)self.data[key] = valuetmpLRUCache = LRUCache_ext1(5)
result = cfp.getTimeMemoryStr(testLRUCache, tmpLRUCache, actions)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 testLRUCache 的运行时间为 420.10 ms;内存使用量为 0.00 KB 执行结果 = 99

3) 改进版二【双向链表+字典】

采用双向链表维护使用顺序,字典保存键值对,要首先定义双向链表类

性能卓越,超过92%在这里插入图片描述

import CheckFuncPerf as cfpclass ListNodeDouble:def __init__(self, key=None, value=None):self.key = keyself.value = valueself.prev = Noneself.next = None
class LRUCache_ext2:def __init__(self, capacity):self.capacity = capacityself.dict = {}self.head = ListNodeDouble()self.tail = ListNodeDouble()self.head.next = self.tailself.tail.prev = self.headdef move_to_tail(self, key):tmpnode = self.dict[key]tmpnode.prev.next = tmpnode.nexttmpnode.next.prev = tmpnode.prevtmpnode.prev = self.tail.prevtmpnode.next = self.tailself.tail.prev.next = tmpnodeself.tail.prev = tmpnodedef get(self, key: int):if key in self.dict:self.move_to_tail(key)result = self.dict.get(key, -1)if result == -1:return resultelse:return result.valuedef put(self, key, value):if key in self.dict:self.dict[key].value = valueself.move_to_tail(key)else:if len(self.dict) == self.capacity:self.dict.pop(self.head.next.key)self.head.next = self.head.next.nextself.head.next.prev = self.headnewkeyval = ListNodeDouble(key, value)self.dict[key] = newkeyvalnewkeyval.prev = self.tail.prevnewkeyval.next = self.tailself.tail.prev.next = newkeyvalself.tail.prev = newkeyvaltmpLRUCache = LRUCache_ext2(5)
result = cfp.getTimeMemoryStr(testLRUCache, tmpLRUCache, actions)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 testLRUCache 的运行时间为 787.18 ms;内存使用量为 0.00 KB 执行结果 = 99

4. 最优算法

根据本地日志分析,最优算法为第2种方式【有序字典】LRUCache_ext1

def testLRUCache(lrucache, actiions):for act in actiions:if len(act) > 1:lrucache.put(act[0], act[1])else:lrucache.get(act[0])return 99
import random
actions = []
iLen = 1000000
for iIdx in range(10):actions.append([iIdx, random.randint(1, 10)])
iturn = 0
for iIdx in range(iLen):if iturn >= 2:actions.append([random.randint(1,10)])else:actions.append([random.randint(1,10), random.randint(1, 1000)])iturn += 1if iturn >= 3:iturn = 0
tmpLRUCache = LRUCache_base(5)
result = cfp.getTimeMemoryStr(testLRUCache, tmpLRUCache, actions)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 算法本地速度实测比较
函数 testLRUCache 的运行时间为 561.12 ms;内存使用量为 4.00 KB 执行结果 = 99
函数 testLRUCache 的运行时间为 420.10 ms;内存使用量为 0.00 KB 执行结果 = 99
函数 testLRUCache 的运行时间为 787.18 ms;内存使用量为 0.00 KB 执行结果 = 99

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

相关文章:

Python算法题集_LRU 缓存

Python算法题集_LRU 缓存 题146&#xff1a;LRU 缓存1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【队列字典】2) 改进版一【有序字典】3) 改进版二【双向链表字典】 4. 最优算法 本文为Python算法题集之一的代码示例 题146&#xff1a;LRU …...

局部加权回归

局部加权回归&#xff08;Local Weighted Regression&#xff09;是一种非参数回归方法&#xff0c;用于解决线性回归模型无法很好拟合非线性数据的问题。它通过给不同的样本赋予不同的权重&#xff0c;使得在拟合模型时更加关注靠近目标点附近的样本数据。 局部加权回归的基本…...

国内国外最好的数据恢复软件评测,哪种数据恢复软件最有效?

随着数字和商业格局在多个领域不断发展&#xff0c;变得更加依赖数据&#xff0c;威胁数据的努力也同样存在。 计算机病毒、勒索软件和恶意软件是导致数据丢失的主要威胁&#xff0c;可能会让您的组织陷入停机或严重影响您的工作效率。而解决这个问题的方法就是数据恢复。 什么…...

bugku 1

Flask_FileUpload 文件上传 先随便传个一句话木马 看看回显 果然不符合规定 而且发现改成图片什么的都不行 查看页面源代码&#xff0c;发现提示 那应该就要用python命令才行 试试ls 类型要改成图片 cat /flag 好像需要密码 bp爆破 根据提示&#xff0c;我们先抓包 爆破 …...

C++ bfs再探迷宫游戏(五十五)【第二篇】

今天我们用bfs解决迷宫游戏。 1.再探迷宫游戏 前面我们已经接触过了迷宫游戏&#xff0c;并且学会了如何使用 DFS 来解决迷宫最短路问题。用 DFS 求解迷宫最短路有一个很大的缺点&#xff0c;需要枚举所有可能的路径&#xff0c;读入的地图一旦很大&#xff0c;可能的搜索方案…...

【Spring原理进阶】SpringMVC调用链+JSP模板应用讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…...

23种计模式之Python/Go实现

目录 设计模式what?why?设计模式&#xff1a;设计模式也衍生出了很多的新的种类&#xff0c;不局限于这23种创建类设计模式&#xff08;5种&#xff09;结构类设计模式&#xff08;7种&#xff09;行为类设计模式&#xff08;11种&#xff09; 六大设计原则开闭原则里氏替换原…...

Qt可视化大屏布局

科技大屏现在非常流行&#xff0c;这里分享一下某个项目的大屏布局&#xff08;忘了源码是哪个博主的了&#xff09; 展示 这个界面整体是垂直布局&#xff0c;分为两个部分&#xff0c;标题是一个部分&#xff0c;然后下面的整体是一个layout布局&#xff0c;为另外一部分。 l…...

re:从0开始的CSS之旅 14. 显示模式的切换

1. 两个属性 display 属性可以用于转换元素的显示模式 可选值&#xff1a; block 转换为块元素 inline 转换为行内元素 inline-block 转换为行内块元素 none 不显示元素&#xff0c;并且不占用元素的位置 visibility 属性用于设置元素是否显示 可选值&#xff1a; visible 显示…...

K8S系列文章之 [Alpine基础环境配置]

用户手册&#xff1a;Alpine User Handbook 官方WIKI&#xff1a;Alpine Linux WIKI 安装 安装的实际逻辑是通过 setup-alpine​ 脚本去调用其他功能的脚本进行配置&#xff0c;可以通过 vi 查看脚本。如果某个部分安装失败&#xff0c;可退出后单独再次执行。通过镜像文件&a…...

单页404源码

<!doctype html> <html> <head> <meta charset"utf-8"> <title>简约 404错误页</title><link rel"shortcut icon" href"./favicon.png"><style> import url("https://fonts.googleapis.co…...

MySQL-运维

一、日志 1.错误日志 错误日志是MySQL中最重要的日志之一&#xff0c;它记录了当mysql启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关性息。当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&#xf…...

Waymo数据集下载与使用

在撰写论文时&#xff0c;接触到一个自动驾驶数据集Waymo Dataset 论文链接为&#xff1a;https://arxiv.org/abs/1912.04838v7 项目链接为&#xff1a;https://github.com/waymo-research/waymo-open-dataset 数据集链接为&#xff1a;https://waymo.com/open waymo提供了两种…...

蓝桥杯每日一题----素数筛

素数筛 素数筛的作用是筛选出[2,N]范围内的所有素数&#xff0c;本次主要讲解两种方法&#xff0c;分别是埃氏筛和欧拉筛。证明时会提到唯一分解定理&#xff0c;如果不知道的小伙伴可以先去学一学&#xff0c;那我们开始啦&#xff01; 1.埃氏筛 主要思想&#xff1a;当找到…...

20240212请问如何将B站下载的软字幕转换成为SRT格式?

20240212请问如何将B站下载的软字幕转换成为SRT格式&#xff1f; 2024/2/12 12:47 百度搜索&#xff1a;字幕 json 转 srt json srt https://blog.csdn.net/a_wh_white/article/details/120687363?share_token2640663e-f468-4737-9b55-73c808f5dcf0 https://blog.csdn.net/a_w…...

《CSS 简易速速上手小册》第6章:高级 CSS 技巧(2024 最新版)

文章目录 6.1 使用 CSS 变量进行设计&#xff1a;魔法配方的调配6.1.1 基础知识6.1.2 重点案例&#xff1a;创建可定制的主题6.1.3 拓展案例 1&#xff1a;响应式字体大小6.1.4 拓展案例 2&#xff1a;使用 CSS 变量创建动态阴影效果 6.2 calc(), min(), max() 等函数的应用&am…...

2024-02-11 多进程、多线程 work

1. 创建一个多进程服务器和多线程服务器 a. 多进程 #include<myhead.h> #define PORT 9999 //端口号 #define IP "192.168.125.113" //IP地址//定义信号处理函数&#xff0c;用于回收僵尸进程 void handler(int signo) {if(signo S…...

详解结构体内存对齐及结构体如何实现位段~

目录 ​编辑 一&#xff1a;结构体内存对齐 1.1对齐规则 1.2.为什么存在内存对齐 1.3修改默认对齐数 二.结构体实现位段 2.1什么是位段 2.2位段的内存分配 2.3位段的跨平台问题 2.4位段的应用 2.5位段使用的注意事项 三.完结散花 悟已往之不谏&#xff0c;知来者犹可…...

Linux网络编程——tcp套接字

文章目录 主要代码关于构造listen监听accepttelnet测试读取信息掉线重连翻译服务器演示 本章Gitee仓库&#xff1a;tcp套接字 主要代码 客户端&#xff1a; #pragma once#include"Log.hpp"#include<iostream> #include<cstring>#include<sys/wait.h…...

【计算机网络】协议层次及其服务模型

协议栈&#xff08;protocol stack&#xff09; 物理层链路层网络层运输层应用层我们自顶向下&#xff0c;所以从应用层开始探究应用层 协议 HTTP 提供了WEB文档的请求和传送SMTP 提供电子邮件报文的传输FTP 提供两个端系统之间的文件传输报文&#xff08;message&#xff09;是…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...