146、LRU缓存-cangjie

devtools/2025/1/3 7:55:26/

题目

146、LRU缓存

思路

  1. 数据结构

    • 使用 HashMap (map) 存储缓存的键值对。键是缓存的键,值是链表节点,可以通过键快速访问。
    • 使用 LinkedList (lists) 来维护缓存的顺序。链表从头到尾表示使用时间,头部是最老的元素,尾部是最近使用的元素。
    • maxSize 是缓存的最大容量。
  2. 初始化

    • 初始化链表和哈希表。在构造函数中,设置最大容量并创建相应的数据结构。
  3. 获取(get)操作

    • 如果键存在于哈希表中:
      • map 中获取对应的链表节点(即存储的键值对)。
      • 读取值,并将对应节点移到链表的尾部(表示最近使用)。
      • 更新哈希表中该键的新位置。
    • 如果键不存在,返回 -1
  4. 插入(put)操作

    • 如果键已经存在:
      • 移除旧节点并在链表中插入新节点(更新为最新的值)。
    • 如果键不存在:
      • 插入新节点到链表尾部。
      • 如果超过最大容量,移除链表头部(最老的元素)和哈希表中对应的键,确保缓存不超过最大容量。

代码

import std.collection.*class LRUCache {var map : HashMap<Int64, LinkedListNode<Array<Int64>>>var lists : LinkedList<Array<Int64>>var maxSize : Int64init(capacity: Int64) {this.lists = LinkedList<Array<Int64>>() // 链表头最老,尾最新// println("init! list size = ${lists.size}")maxSize = capacitythis.map = HashMap<Int64, LinkedListNode<Array<Int64>>>()}func get(key: Int64): Int64 {// println("get in!")if(map.contains(key)){let oldNode = map[key]var val = oldNode.value[1]// println("get node val ${val}")let newNode = lists.append([key,val])lists.remove(oldNode)map.put(key, newNode)return val}return -1}func put(key: Int64, value: Int64): Unit {// println("put in!")if(map.contains(key)){lists.remove(map[key])let node = lists.append([key,value])map.put(key, node)// println("refresh! list size = ${lists.size}")}else{let node = lists.append([key,value])map.put(key, node)// println("put! list size = ${lists.size}")// println("newNode info : ${node.value[0]}, ${node.value[1]}")if(lists.size > maxSize){// println("cache oversize! remove head")map.remove((lists.firstNode()??throw Exception("er")).value[0])lists.remove((lists.firstNode()??throw Exception("er")))// println("remove over! list size = ${lists.size}")}}}
}/*** Your LRUCache object will be instantiated and called as such:* let obj: LRUCache = LRUCache(capacity)* let param_1 = obj.get(key)* obj.put(key,value)*/

复杂度

时间复杂度

  1. get操作

    • 在哈希表中查找键是 O(1) 的时间复杂度。
    • 移动节点在链表中(移除和插入)也是在 O(1) 的时间复杂度。
    • 因此,get 的总时间复杂度是 O(1)
  2. put操作

    • 查找键操作为 O(1)。
    • 移动节点的操作也是 O(1)。
    • 若需移除链表头部元素,时间复杂度为 O(1)。
    • 因此,put 的总时间复杂度也是 O(1)

空间复杂度

  • HashMapLinkedList 都存储相同数量的元素,因此空间复杂度是 O(n),其中 n 是当前缓存中存储的元素数量。
  • 由于只存储活动的缓存项,所以最大空间复杂度为 O(n),与最大容量相同。

遇到的坑

1、为了实现插入后删除最老,需要从ListNode反查key,所以LinkedListNode需要存储kvpair,不能只存一个value
2、双向链表节点获取问题

map.remove((lists.firstNode()??throw Exception("er")).value[0])
lists.remove((lists.firstNode()??throw Exception("er")))

老生常谈了,option类型的返回值函数需要??判断是否抛错误

public func firstNode(): Option<LinkedListNode<T>>

3、初始化问题
不知道为什么this.map = HashMap<Int64, LinkedListNode<Array<Int64>>>(capacity, lists.firstNode()??throw Exception("error"))会要(Int64) ->Tuple, (capacity, lists.firstNode()??throw Exception("error"))这个不已经是tuple类型了嘛

this.map = HashMap<Int64, LinkedListNode<Array<Int64>>>() // ok,size = 0
this.map = HashMap<Int64, LinkedListNode<Array<Int64>>>((capacity, lists.firstNode()??throw Exception("error"))) // ok,但是需要list初始化的时候起一个头节点 例如先lists.append([0,0])
this.map = HashMap<Int64, LinkedListNode<Array<Int64>>>(capacity, lists.firstNode()??throw Exception("error")) // 不ok,报错如下

在这里插入图片描述

结果

cangjie


http://www.ppmy.cn/devtools/131263.html

相关文章

基于yolov5的输电线,电缆检测系统,支持图像检测,视频检测和实时摄像检测功能(pytorch框架,python源码)

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; yolov5&#xff0c;输电线(线缆)检测系统&#xff0c;系统既支持图像检测&#xff0c;也支持视频和摄像实时检测【pytorch框架】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的输…

HarmonyOS鸿蒙开发入门,常用ArkUI组件学习(一)

刚开始接触HarmonyOS的开发&#xff0c;希望不会太晚。在我学习的过程中&#xff0c;我会将我学到的内容&#xff0c;通过写博客的形式&#xff0c;来进行回忆和复习。同时也希望能够遇到志同道合的朋友&#xff0c;我们一起学习&#xff0c;一起进步&#xff0c;文章中有什么不…

24/11/3 算法笔记 Adam优化器拆解

Adam 优化器是一种用于深度学习中的自适应学习率优化算法&#xff0c;它结合了两种其他流行的优化方法的优点&#xff1a;RMSprop 和 Momentum。简单来说&#xff0c;Adam 优化器使用了以下方法&#xff1a; 1. **指数加权移动平均&#xff08;Exponentially Weighted Moving …

利用Python进行数据可视化:实用指南与推荐库

利用Python进行数据可视化:实用指南与推荐库 数据可视化是将数据转化为图形和图表的过程,它能够帮助我们更直观地理解数据的趋势、模式和关系。在Python中,有许多强大的库可用于数据可视化,从简单的折线图到复杂的交互式图表,应有尽有。本文将详细介绍Python数据可视化的…

k8s 小版本升级

众所周知k8s每一个月左右都会更新一次小版本所以在 Kubernetes 生态系统中&#xff0c;保持集群的版本更新是至关重要的。这不仅能够带来新的特性和改进&#xff0c;还能确保集群的安全性和稳定性。随着 Kubernetes 项目的快速发展&#xff0c;小版本的升级成为了集群维护的一个…

微服务设计模式 - 网关路由模式(Gateway Routing Pattern)

微服务设计模式 - 网关路由模式&#xff08;Gateway Routing Pattern&#xff09; 定义 网关路由模式&#xff08;Gateway Routing Pattern&#xff09;是微服务架构中一种非常重要的设计模式&#xff0c;主要用于在客户端和微服务之间提供一个中间层。这一模式通过中央网关路…

elementUI table 多级表头隔行变背景颜色

效果图如下&#xff1a; 代码如下&#xff1a; 其中rowIndex 0 意思为多级表头的第一行&#xff0c;columnIndex 0 意思为某一行的第一列 如 rowIndex 0&#xff0c; columnIndex 1 的意思为多级表头的第一行中的第二列 指在上效果图中 激活指标 如 rowIndex 1&#x…

无人机避障——2D栅格地图pgm格式文件路径规划代码详解

代码和测试效果请看上一篇博客&#xff1a; 无人机避障——使用三维PCD点云生成的2D栅格地图PGM做路径规划-CSDN博客 更换模型文件.dae&#xff1a; 部分模型文件可以从这里下载&#xff1a; https://github.com/ethz-asl/rotors_simulator/wiki 将原先代码中的car.dae文件…