O(1)插入、删除和随机元素[中等]

优质博文:IT-BLOG-CN
在这里插入图片描述

一、题目

实现RandomizedSet类:
【1】RandomizedSet()初始化RandomizedSet对象。
【2】bool insert(int val)当元素val不存在时,向集合中插入该项,并返回true;否则,返回false
【3】bool remove(int val)当元素val存在时,从集合中移除该项,并返回true;否则,返回false
【4】int getRandom()随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。

你必须实现类的所有函数,并满足每个函数的平均时间复杂度为O(1)

示例:
输入: ["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"] :[[], [1], [2], [2], [], [1], [2], []]
输出:[null, true, false, true, 2, true, false, 2]

解释:

RandomizedSet randomizedSet = new RandomizedSet();  
randomizedSet.insert(1); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。  
randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。  
randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。  
randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。  
randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。  
randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。  
randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。  

-231 <= val <= 231 - 1
在调用getRandom方法时,数据结构中 至少存在一个 元素。

二、代码

思路:
【1】变长数组List可以在O(1)的时间内完成获取随机元素操作,但是由于无法在O(1)的时间内判断元素是否存在,因此不能在O(1)的时间内完成插入和删除操作。
【2】哈希表可以在O(1)的时间内完成插入和删除操作,但是由于无法根据下标定位到特定元素,因此不能在O(1)的时间内完成获取随机元素操作。
【3】为了满足插入、删除和获取随机元素操作的时间复杂度都是O(1)需要将变长数组和哈希表结合,变长数组中存储元素,哈希表中存储每个元素在变长数组中的下标

// 空间换时间
class RandomizedSet {Map<Integer,Integer> map;List<Integer> list;Random random;public RandomizedSet() {map = new HashMap<>();list = new ArrayList();random = new Random();}public boolean insert(int val) {// 判断value是否存在,存在直接返回falseif(map.containsKey(val)) {return false;}// 插入 0(1) 使用 map[key = val , value = index] 数组的长度=数据的下标map.put(val, list.size());// list中存放 vallist.add(val);return true;}// 删除操作的重点在于将变长数组的最后一个元素移动到待删除元素的下标处,然后删除变长数组的最后一个元素。// 该操作的时间复杂度是 O(1),且可以保证在删除操作之后变长数组中的所有元素的下标都连续,方便插入操作和获取随机元素操作。public boolean remove(int val) {if (!map.containsKey(val)) {return false;}// 思想:list 的 udpate 是 O(1) 所以使用 list中的最后一个元素修改 index 下表的元素// 通过map获取指定val的下表int index = map.get(val);// 获取list中最后一个元素int last = list.get(list.size() - 1);// 使用最后一个元素替换list中的index元素list.set(index, last);// map 也需要更新最后一个元素 last 的下标map.put(last, index);// 删除list和maplist.remove(list.size() - 1);map.remove(val);return true;}// 获取随机元素操作时,由于变长数组中的所有元素的下标都连续,因此随机选取一个下标,返回变长数组中该下标处的元素public int getRandom() {int randomIndex = random.nextInt(list.size());return list.get(randomIndex);}
}/*** Your RandomizedSet object will be instantiated and called as such:* RandomizedSet obj = new RandomizedSet();* boolean param_1 = obj.insert(val);* boolean param_2 = obj.remove(val);* int param_3 = obj.getRandom();*/

变长数组 + 哈希表: 这道题要求实现一个类,满足插入、删除和获取随机元素操作的平均时间复杂度为O(1)

变长数组可以在O(1)的时间内完成获取随机元素操作,但是由于无法在O(1)的时间内判断元素是否存在,因此不能在O(1)的时间内完成插入和删除操作。哈希表可以在O(1)的时间内完成插入和删除操作,但是由于无法根据下标定位到特定元素,因此不能在O(1)的时间内完成获取随机元素操作。为了满足插入、删除和获取随机元素操作的时间复杂度都是O(1),需要将变长数组和哈希表结合,变长数组中存储元素,哈希表中存储每个元素在变长数组中的下标。

插入操作时,首先判断val是否在哈希表中,如果已经存在则返回false,如果不存在则插入val,操作如下:
1、在变长数组的末尾添加val
2、在添加val之前的变长数组长度为val所在下标index,将val和下标index存入哈希表;
3、返回true

删除操作时,首先判断val是否在哈希表中,如果不存在则返回false,如果存在则删除val,操作如下:
1、从哈希表中获得val的下标index
2、将变长数组的最后一个元素last移动到下标index处,在哈希表中将last的下标更新为index
3、在变长数组中删除最后一个元素,在哈希表中删除val
4、返回true

删除操作的重点在于将变长数组的最后一个元素移动到待删除元素的下标处,然后删除变长数组的最后一个元素。该操作的时间复杂度是 O(1),且可以保证在删除操作之后变长数组中的所有元素的下标都连续,方便插入操作和获取随机元素操作。

获取随机元素操作时,由于变长数组中的所有元素的下标都连续,因此随机选取一个下标,返回变长数组中该下标处的元素。

class RandomizedSet {List<Integer> nums;Map<Integer, Integer> indices;Random random;public RandomizedSet() {nums = new ArrayList<Integer>();indices = new HashMap<Integer, Integer>();random = new Random();}public boolean insert(int val) {if (indices.containsKey(val)) {return false;}int index = nums.size();nums.add(val);indices.put(val, index);return true;}public boolean remove(int val) {if (!indices.containsKey(val)) {return false;}int index = indices.get(val);int last = nums.get(nums.size() - 1);nums.set(index, last);indices.put(last, index);nums.remove(nums.size() - 1);indices.remove(val);return true;}public int getRandom() {int randomIndex = random.nextInt(nums.size());return nums.get(randomIndex);}
}

时间复杂度: 初始化和各项操作的时间复杂度都是O(1)
空间复杂度: O(n),其中 nnn 是集合中的元素个数。存储元素的数组和哈希表需要O(n)的空间。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法与数据结构】343、LeetCode整数拆分

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;博主做这道题的时候一直在思考&#xff0c;如何找到 k k k个正整数&#xff0c; k k k究竟为多少合适。…

2018年认证杯SPSSPRO杯数学建模B题(第二阶段)动态模糊图像全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 动态模糊图像复原 B题 动态模糊图像 原题再现&#xff1a; 人眼由于存在视觉暂留效应&#xff0c;所以看运动的物体时&#xff0c;看到的每一帧画面都包含了一段时间内 (大约 1/24 秒) 的运动过程&#xff0c;所以这帧画面事实上是模糊的。对…

C#:接口中如何将某个值类型的字段传null?

在实际对接第三方接口时&#xff0c;偶尔会有一些字段在某些情况下是不需要传值的。那如何处理呢&#xff1f; 有两种方法&#xff1a; 1、将值类型改为可空类型&#xff1b; 2、定义基类&#xff0c;基类包含所有必须要传的字段&#xff0c;子类则加入偶尔需要传的字段。 下…

玖章算术NineData通过阿里云PolarDB产品生态集成认证

近日&#xff0c;玖章算术旗下NineData 云原生智能数据管理平台 (V1.0&#xff09;正式通过了阿里云PolarDB PostgreSQL版 (V11)产品集成认证测试&#xff0c;并获得阿里云颁发的产品生态集成认证。 测试结果表明&#xff0c;玖章算术旗下NineData数据管理平台 (V1.0&#xff…

基于高斯过程的贝叶斯优化

基于Bayes_opt实现GP优化 bayes-optimization是最早开源的贝叶斯优化库之一&#xff0c;也是为数不多至今依然保留着高斯过程优化的优化库。由于开源较早、代码简单&#xff0c;bayes-opt常常出现在论文、竞赛kernels或网络学习材料当中&#xff0c;因此理解Bayes_opt的代码是…

IMDB电影评论的情感分析——paddle

项目地址&#xff1a;IMDB电影评论的情感分析 - 飞桨AI Studio星河社区 (baidu.com) 1. 实验介绍 1.1 实验目的 理解并掌握循环神经网络的基础知识点&#xff0c;包括模型的时序结构、模型的前向传播、反向传播等掌握长短时记忆网络LSTM和门控循环单元网络GRU的设计原理熟悉如…

【02】mapbox js api加载arcgis切片服务

需求&#xff1a; 第三方的mapbox js api加载arcgis切片服务&#xff0c;同时叠加在mapbox自带底图上 效果图&#xff1a; 形如这种地址去加载&#xff1a; http://zjq2022.gis.com:8080/demo/loadmapbox.html arcgis切片服务参考链接思路&#xff1a;【01】mapbox js api加…

高光谱分类论文解读分享之Grid Network: 基于各向异性视角下特征提取的高光谱影像分类

IEEE GRSL 2023&#xff1a;Grid Network: 基于各向异性视角下特征提取的高光谱影像分类 题目 Grid Network: Feature Extraction in Anisotropic Perspective for Hyperspectral Image Classification 作者 Zhonghao Chen , Student Member, IEEE, Danfeng Hong , Senior …

非常好用的Mac清理工具CleanMyMac X 4.14.7 如何取消您对CleanMyMac X的年度订购

CleanMyMac X 4.14.7是Mac平台上的一款非常著名同时非常好用的Mac清理工具。全方位扫描您的Mac系统&#xff0c;让垃圾无处藏身&#xff0c;您只需要轻松单击2次鼠标左键即可清理数G的垃圾&#xff0c;就这么简单。瞬间提升您Mac速度。 CleanMyMac X 4.14.7下载地址&#xff1a…

2018年认证杯SPSSPRO杯数学建模D题(第二阶段)投篮的最佳出手点全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 D题 投篮的最佳出手点 原题再现&#xff1a; 影响投篮命中率的因素不仅仅有出手角度、球感、出手速度&#xff0c;还有出手点的选择。规范的投篮动作包含两膝微屈、重心落在两脚掌上、下肢蹬地发力、身体随之向前上方伸展、同时抬肘向投篮方向…

低代码自动化测试的实践

何为低代码测试 传统上&#xff0c;功能、 UI、端到端等测试自动化的实现都涉及编写测试脚本&#xff0c;代替测试人员执行重复的手动测试任务。自动化脚本的开发工作通常由 QA 工程师或开发人员完成&#xff0c;这需要编写大量代码。 而低代码甚至无代码的理念也是在自动化测…

基于arcgis js api 4.x开发点聚合效果

一、代码 <html> <head><meta charset"utf-8" /><meta name"viewport"content"initial-scale1,maximum-scale1,user-scalableno" /><title>Build a custom layer view using deck.gl | Sample | ArcGIS API fo…