LeetCode题练习与总结:O(1) 时间插入、删除和获取随机元素--380

一、题目描述

实现RandomizedSet 类:

  • RandomizedSet() 初始化 RandomizedSet 对象
  • bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。
  • bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false 。
  • 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 。

提示:

  • -2^31 <= val <= 2^31 - 1
  • 最多调用 insertremove 和 getRandom 函数 2 * 10^5 次
  • 在调用 getRandom 方法时,数据结构中 至少存在一个 元素。

二、解题思路

为了实现 RandomizedSet 类,我们需要保证 insertremove 和 getRandom 操作的平均时间复杂度为 O(1)。为了达到这个目标,我们可以使用以下数据结构:

  1. 动态数组(ArrayList):用于存储集合中的元素,这样可以在 O(1) 时间内通过索引访问到任何元素。
  2. 哈希表(HashMap):用于存储每个元素值与其在动态数组中索引的映射,这样可以在 O(1) 时间内检查元素是否存在以及获取其索引。

以下是解题思路:

  • 插入操作(insert)

    • 使用哈希表检查元素是否已存在。
    • 如果不存在,将其添加到动态数组的末尾,并在哈希表中记录其索引。
  • 删除操作(remove)

    • 使用哈希表检查元素是否存在以及其索引。
    • 如果存在,将数组中该元素与最后一个元素交换位置,然后删除数组末尾的元素,并更新哈希表中的索引映射。
  • 获取随机元素(getRandom)

    • 由于数组中的元素是连续存储的,我们可以通过生成一个随机索引来直接访问数组中的随机元素。

三、具体代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;public class RandomizedSet {private Map<Integer, Integer> indexMap;private List<Integer> nums;private Random rand;public RandomizedSet() {indexMap = new HashMap<>();nums = new ArrayList<>();rand = new Random();}public boolean insert(int val) {if (indexMap.containsKey(val)) {return false;}indexMap.put(val, nums.size());nums.add(val);return true;}public boolean remove(int val) {if (!indexMap.containsKey(val)) {return false;}int lastElement = nums.get(nums.size() - 1);int idxToRemove = indexMap.get(val);nums.set(idxToRemove, lastElement);indexMap.put(lastElement, idxToRemove);nums.remove(nums.size() - 1);indexMap.remove(val);return true;}public int getRandom() {return nums.get(rand.nextInt(nums.size()));}
}

这段代码实现了 RandomizedSet 类,满足了题目要求的 O(1) 时间复杂度。每次插入和删除操作都会更新哈希表和动态数组,而获取随机元素则直接从动态数组中随机选择一个索引。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 构造函数 RandomizedSet():

    • 初始化 indexMap 和 nums 的时间复杂度是 O(1)。
    • 初始化 rand 的时间复杂度也是 O(1)。
    • 因此,总的时间复杂度是 O(1)。
  • 方法 insert(int val):

    • 检查元素是否存在于哈希表中,时间复杂度是 O(1)。
    • 如果元素不存在,则添加到动态数组和哈希表中,添加到数组和哈希表的操作时间复杂度都是 O(1)。
    • 因此,总的时间复杂度是 O(1)。
  • 方法 remove(int val):

    • 检查元素是否存在于哈希表中,时间复杂度是 O(1)。
    • 如果元素存在,则需要交换待删除元素与数组末尾元素的位置,并更新哈希表,这些操作的时间复杂度都是 O(1)。
    • 删除数组末尾元素,时间复杂度是 O(1)。
    • 从哈希表中删除元素,时间复杂度也是 O(1)。
    • 因此,总的时间复杂度是 O(1)。
  • 方法 getRandom():

    • 生成随机索引,时间复杂度是 O(1)。
    • 通过索引访问数组元素,时间复杂度是 O(1)。
    • 因此,总的时间复杂度是 O(1)。
2. 空间复杂度
  • 构造函数 RandomizedSet():

    • indexMap 和 nums 都是动态数据结构,它们的空间复杂度取决于集合中元素的数量。
    • rand 是一个轻量级的对象,它占用的空间可以认为是 O(1)。
    • 因此,总的空间复杂度是 O(n),其中 n 是集合中元素的数量。
  • 方法 insert(int val):

    • 没有使用额外的空间,除了在 nums 和 indexMap 中存储元素。
    • 因此,空间复杂度是 O(1)。
  • 方法 remove(int val):

    • 同样,没有使用额外的空间。
    • 因此,空间复杂度是 O(1)。
  • 方法 getRandom():

    • 没有使用额外的空间。
    • 因此,空间复杂度是 O(1)。
3. 总结
  • 时间复杂度:

    • 构造函数:O(1)
    • insert(int val):O(1)
    • remove(int val):O(1)
    • getRandom():O(1)
  • 空间复杂度:

    • 构造函数:O(n)
    • insert(int val):O(1)
    • remove(int val):O(1)
    • getRandom():O(1)

其中 n 是集合中元素的数量。注意,虽然单个操作的空间复杂度是 O(1),但是随着集合中元素数量的增加,整体空间需求会线性增长。

五、总结知识点

  • 类定义:

    • public class RandomizedSet 定义了一个公共类 RandomizedSet
  • 成员变量:

    • private Map<Integer, Integer> indexMap; 定义了一个私有成员变量 indexMap,用于存储元素值与其在动态数组中的索引的映射。
    • private List<Integer> nums; 定义了一个私有成员变量 nums,用于存储集合中的元素。
    • private Random rand; 定义了一个私有成员变量 rand,用于生成随机数。
  • 构造函数:

    • public RandomizedSet() 是类的构造函数,用于初始化成员变量。
  • 哈希表(HashMap):

    • indexMap 是一个 HashMap,它提供了 O(1) 时间复杂度的查找、插入和删除操作。
  • 动态数组(ArrayList):

    • nums 是一个 ArrayList,它支持动态数组操作,如添加、删除和通过索引访问元素。
  • 随机数生成(Random):

    • rand 是 Random 类的一个实例,用于生成随机数。
  • 方法定义:

    • public boolean insert(int val) 定义了一个公共方法,用于向集合中插入一个元素。
    • public boolean remove(int val) 定义了一个公共方法,用于从集合中移除一个元素。
    • public int getRandom() 定义了一个公共方法,用于从集合中随机获取一个元素。
  • 条件判断:

    • if (indexMap.containsKey(val)) 用于检查元素是否已经在集合中。
    • if (!indexMap.containsKey(val)) 用于检查元素是否不在集合中。
  • 哈希表操作:

    • indexMap.put(val, nums.size()); 将元素值和其在数组中的索引插入哈希表。
    • indexMap.remove(val); 从哈希表中移除一个元素。
  • 数组操作:

    • nums.add(val); 在数组的末尾添加一个元素。
    • nums.set(idxToRemove, lastElement); 通过索引设置数组中的元素。
    • nums.remove(nums.size() - 1); 移除数组末尾的元素。
  • 随机数的使用:

    • rand.nextInt(nums.size()); 生成一个介于 0(包含)和 nums.size()(不包含)之间的随机整数,用于随机访问数组元素。
  • 返回值:

    • return true; 和 return false; 分别用于表示操作成功或失败。
    • return nums.get(rand.nextInt(nums.size())); 返回一个随机选择的数组元素。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

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

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

相关文章

39页PDF | 华为数据架构建设交流材料(限免下载)

一、前言 这份报告是关于企业数据架构建设的交流材料&#xff0c;详细介绍了数据架构在企业架构中的重要性&#xff0c;阐述了数据架构的定义、包含的四个核心组件&#xff08;数据资产目录、数据标准、数据模型和数据分布&#xff09;&#xff0c;并通过交通和城市政务服务的…

三周精通FastAPI:27 使用使用SQLModel操作SQL (关系型) 数据库

官网文档&#xff1a;https://fastapi.tiangolo.com/zh/tutorial/sql-databases/ SQL (关系型) 数据库 FastAPI不需要你使用SQL(关系型)数据库。 但是您可以使用任何您想要的关系型数据库。 这里我们将看到一个使用SQLModel的示例。 SQLModel是在SQLAlchemy和Pydantic的基础…

专业140+总分430+四川大学854信号与系统考研川大原951电子信息与通信工程,真题,大纲,参考书。

川大854(原951)信号与系统140&#xff0c;总分430&#xff0c;顺利上岸&#xff0c;目前已经研究生在读&#xff0c;群里不少同学希望分享一下我的考研经历&#xff0c;回首考研这一年的复习经历&#xff0c;历历在目&#xff0c;好像就在昨天&#xff0c;期间有过迷惑&#xf…

蓝桥杯第21场小白入门赛补题

5.蓝桥派对 思路 &#xff1a;一个区间与多少个其他区间有关联&#xff0c;先对所有区间左端点和右端点从小到大排序&#xff0c;对于每个询问&#xff0c;我们先算出[1,r]这个区间里有多少个区间的起点即区间总数&#xff0c;使用upper_bound函数&#xff0c;然后使用lower_bo…

【再谈设计模式】原型模式~复制的魔法师

一、引言 在软件工程、软件开发中&#xff0c;创建对象的过程常常涉及复杂的初始化和配置。在某些情况下&#xff0c;直接复制现有对象比从头开始创建新对象更为高效。原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;允许我们通过复制现有…

技术分享 —— JMeter接口与性能测试实战!

前言 在软件开发和运维过程中&#xff0c;接口性能测试是一项至关重要的工作。JMeter作为一款开源的Java应用&#xff0c;被广泛用于进行各种性能测试&#xff0c;包括接口性能测试。本文将详细介绍如何使用JMeter进行接口性能测试的过程和步骤。 JMeter是Apache组织开发的基…

Data+AI━━数据安全的警钟:智能化分类分级治理

DataAI━━数据安全的警钟&#xff1a;智能化分类分级治理 前言数据的分类体系数据分级与智能化实践深度案例解析与未来展望 前言 OpenAI数据泄露事件让数据安全再次成为科技圈的热门话题。2024年3月,一名研究员发现OpenAI的API存在安全漏洞,导致部分用户的对话记录泄露。 这一…

【K8S问题系列】Kubernetes Pod节点CrashLoopBackOff 状态【已解决】

在 Kubernetes 中&#xff0c;Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃&#xff0c;Kubernetes 尝试重启该容器&#xff0c;但由于持续崩溃&#xff0c;重启的间隔时间逐渐增加。下面将详细介绍 CrashLoopBackOff 状态的原因、解决方案及相关命令的输出解释。 …

图像信号处理器(ISP,Image Signal Processor)详解

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 图像信号处理器&#xff08;ISP&#xff0c;Image Signal Processor&#xff09; 是专门用于处理图像信号的硬件或处理单元&#xff0c;广泛应用于图像传感器&#xff08;如 CMOS 或 CCD 传感器&a…

u盘怎么重装电脑系统_u盘重装电脑系统步骤和详细教程【新手宝典】

u盘怎么重装电脑系统&#xff1f;一个u盘怎么重装电脑系统呢&#xff0c;需要将u盘制作成u盘启动盘pe&#xff0c;然后通过U盘启动盘进入pe进行安装系统&#xff0c;下面小编就教大家u盘重装电脑系统步骤和详细教程。 u盘启动是什么意思&#xff1f; U盘启动盘是一种具有特殊功…

SpringBoot健身房管理:技术与实践

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

Sigrity Power SI 3D-EM Inductance Extraction模式如何进行电感的提取操作指导(一)

Sigrity Power SI 3D-EM Inductance Extraction模式如何进行电感的提取操作指导(一) Sigrity Power SI使用3D-EM Inductance Extraction模式可以进行电感的提取,以下图为例 2D 视图 <

Fsm serialdata

现在您有了一个有限状态机&#xff0c;可以识别串行比特流中何时正确接收字节&#xff0c;添加一个数据路径&#xff0c;输出正确接收的数据字节。当done为1时&#xff0c;out_byte必须有效&#xff0c;否则为not。 请注意&#xff0c;串行协议首先发送最低有效位。 此题&#…

【GESP】C++一级真题练习(202309)luogu-B3863,买文具

GESP一级真题练习。为2023年9月一级认证真题。属于数值计算条件判断的问题。 题目题解详见&#xff1a;https://www.coderli.com/gesp-1-luogu-b3863/ 【GESP】C一级真题练习(202309)luogu-B3863&#xff0c;买文具 | OneCoderGESP一级真题练习。为2023年9月一级认证真题。属…

《Python游戏编程入门》注-第5章4

2.3 随机改变颜色 从图1中可以看出,当完全显示了一个大圆之后,会改变颜色继续显示该大圆。也就是当圆心角angle的值大于等于360度时,随机改变颜色,代码如图6所示。 图6 随机改变颜色的代码 其中,第18行代码判断是否完全显示了一个大圆,如果是,圆心角的角度设置为0,第…

健康生活,注重养生

在快节奏的现代生活中&#xff0c;健康养生已成为我们不可忽视的重要课题。它不仅仅关乎身体的强健&#xff0c;更涉及到心灵的平和与愉悦。以下是一些实用的健康养生建议&#xff0c;帮助我们在日常生活中&#xff0c;以自然和谐的方式&#xff0c;滋养身心&#xff0c;享受生…

气膜体育馆:高效便捷的现代运动新选择—轻空间

随着城市发展和人们健康意识的提高&#xff0c;体育场馆的需求日益增加。然而&#xff0c;传统体育馆的建设周期长、成本高和多功能性有限&#xff0c;往往无法满足快速发展的城市需求。那么&#xff0c;为什么选择气膜体育馆作为您的场馆建设方案呢&#xff1f;今天&#xff0…

SSLHandshakeException错误解决方案

1、错误提示 调用Http工具报如下异常信息&#xff1a; cn.hutool.core.io.IORuntimeException: SSLHandshakeException: Received fatal alert: handshake_failure2、查询问题 一开始我以为是代码bug&#xff0c;网络bug甚至是配置环境未生效&#xff0c;找了一大圈&#xf…

第十八周:机器学习

目录 摘要 abstract 一、BERT 1、应用场景 任务一&#xff1a;单句子分类任务 任务二&#xff1a;单句子标注任务 任务三&#xff1a;句子对分类任务 任务四&#xff1a;问答系统 2、pre-train model 3、fine tune微调 input&output how to fine tune 二、…

从0开始搭建一个生产级SpringBoot2.0.X项目(十二)SpringBoot接口SpringSecurity JWT鉴权

前言 最近有个想法想整理一个内容比较完整springboot项目初始化Demo。 SpringBoot接口权限控制 SpringSecurity 接口使用 Bearer token类型 JWT 鉴权 一、pom文件新增依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>s…