2024.4.26力扣每日一题——快照数组

server/2024/10/18 12:32:03/

2024.4.26

      • 题目来源
      • 我的题解
        • 方法一 TreeMap
        • 方法二 哈希表+二分法

题目来源

力扣每日一题;题序:1146

我的题解

方法一 TreeMap

使用TreeMap记录每个snip_id下的修改记录。
在set时,判断snip_id下是否有修改记录,若无则将最后一次有修改记录的snip_id下的修改记录复制给当前的snip_id,然后再添加新的修改记录。
在snap时只需要直接snip_id+1
在get时,从snip_id开始遍历,依次减1,找到最后一次index修改的记录。

时间复杂度:初始化、snap 均为 O(1),set为O(logn),get 为 O(h+k),h是查找快照ID时需要遍历的层数(从snap_id到0),k是找到特定索引的值所需的映射查找次数。在最坏的情况下,如果每次快照都修改了该索引,那么k可以是等于快照数量的。但是,如果快照修改不是那么频繁,这个值会小得多。
空间复杂度:除了初始化基本都是O(1)

java">class SnapshotArray {TreeMap<Integer,Map<Integer,Integer>> map;int[] arr;int count;int len;public SnapshotArray(int length) {map=new TreeMap<>();arr=new int[length];count=0;len=length;map.put(0,new HashMap<>());}public void set(int index, int val) {if(!map.containsKey(count)&&count!=0)map.put(count,new HashMap<>(map.get(map.lastKey())));Map<Integer,Integer> change=map.get(count);change.put(index,val);map.put(count,change);}public int snap() {return count++;}public int get(int index, int snap_id) {int res=arr[index];for(int i=snap_id;i>=0;i--){if(map.containsKey(i)&&map.get(i).containsKey(index)){res=map.get(i).get(index);break;}}return res;}
}
方法二 哈希表+二分法

参照灵神的代码

时间复杂度:初始化、set、snap 均为 O(1),get为 O(log⁡q),其中 q 为 set 的调用次数。
空间复杂度:O(q)

java">class SnapshotArray {// 当前快照编号,初始值为 0private int curSnapId;// 每个 index 的历史修改记录private final Map<Integer, List<int[]>> history = new HashMap<>();public SnapshotArray(int length) {}public void set(int index, int val) {history.computeIfAbsent(index, k -> new ArrayList<>()).add(new int[]{curSnapId, val});}public int snap() {return curSnapId++;}public int get(int index, int snapId) {if (!history.containsKey(index)) {return 0;}List<int[]> h = history.get(index);int j = search(h, snapId);return j < 0 ? 0 : h.get(j)[1];}// 返回最大的下标 i,满足 h[i][0] <= x// 如果不存在则返回 -1private int search(List<int[]> h, int x) {// 开区间 (left, right)int left = -1;int right = h.size();while (left + 1 < right) { // 区间不为空// 循环不变量:// h[left][0] <= x// h[right][1] > xint mid = left + (right - left) / 2;if (h.get(mid)[0] <= x) {left = mid; // 区间缩小为 (mid, right)} else {right = mid; // 区间缩小为 (left, mid)}}// 根据循环不变量,此时 h[left][0] <= x 且 h[left+1][0] = h[right][0] > x// 所以 left 是最大的满足 h[left][0] <= x 的下标// 如果不存在,则 left 为其初始值 -1return left;}
}

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~


http://www.ppmy.cn/server/20291.html

相关文章

Redis分布式锁手动实现

Redis分布式锁手动实现 java中锁机制 在 Java 中&#xff0c;锁是用来同步并发访问共享资源的机制。它确保了在一个时间点&#xff0c;只有一个线程可以执行某个代码块或方法&#xff0c;从而防止了数据的不一致和竞态条件。Java 提供了多种锁机制&#xff0c;包括内置锁&…

基于ssm + 小程序的党建考试系统实现与设计(源码+数据库+文档)

基于ssm 小程序的“党建考试系统”实现与设计&#xff08;源码数据库文档) 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringmvcSpringMybatis、vue、小程序工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 管理系统-登录界面展示 管理系统…

【嵌入式AI开发】轻量级卷积神经网络MobileNetV2详解

前言:MobileNetV2网络先升维后降维,在降维时使用线性激活函数,带残差的Inverted bottleck模块,防止ReLU信息丢失。在图像分类、目标检测、语义分割等任务上实现了网络轻量化、速度和准确度的权衡。 回顾MobileNetV1的理论和MobileNetV2项目实战可查阅如下链接: 【嵌入式AI…

Docker在Windows与CentOS上的安装

这个季节有着无数的热烈&#xff0c;就像是飞鸟对天空的迫切。大家好&#xff0c;今天给大家分享一下关于Docker的安装&#xff0c;那么作为一名软件测试工程师&#xff0c;为什么需要了解Docker并且使用Docker呢&#xff1f;Docker会给我们带来怎样的好处呢&#xff1f; 原因…

esp32s3中使用双通道通信解决TCP粘包问题

在使用esp32 idf例程中的tcp_server和tcp_client通信测试时发现&#xff0c; 在tcp_server端&#xff0c;接收到一帧数据之后必须马上回复至少一个字节&#xff0c;才能保证每帧数据不粘包&#xff0c; 如果不回复操作&#xff0c;300ms以内的通信时延会导致tcp严重粘包&…

OceanBase 分布式数据库【信创/国产化】- OceanBase Demo 环境搭建

本心、输入输出、结果 文章目录 OceanBase 分布式数据库【信创/国产化】- OceanBase Demo 环境搭建前言OceanBase 数据更新架构部署背景信息组件介绍部署前提条件下载并安装 all-in-one 安装包单机部署 OceanBase 数据库执行输出中的连接命令连接数据库配置 OceanBase 密码Ocea…

Linux - tar (tape archive)

tar 的全称是 Tape Archive。它最初是在 Unix 系统中用于将数据写入磁带的工具&#xff0c;但现在它通常用于创建、维护、修改和提取文件的归档文件。尽管 tar 可以用于压缩和解压缩文件&#xff0c;但它本身并不进行压缩&#xff0c;而是通常与 gzip 或 bzip2 等压缩工具一起使…

腾讯云邮件推送如何设置?群发邮件的技巧?

腾讯云邮件推送功能有哪些&#xff1f;怎么有效使用邮件推送&#xff1f; 腾讯云邮件推送以其稳定、高效的特点&#xff0c;受到了众多企业的青睐。那么&#xff0c;腾讯云邮件推送如何设置呢&#xff1f;又有哪些群发邮件的技巧呢&#xff1f;下面AokSend就来详细探讨一下。 …