力扣381. O(1) 时间插入、删除和获取随机元素 - 允许重复

2024-02-29 11:28

本文主要是介绍力扣381. O(1) 时间插入、删除和获取随机元素 - 允许重复,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

RandomizedCollection 是一种包含数字集合(可能是重复的)的数据结构。它应该支持插入和删除特定元素,以及删除随机元素。

实现 RandomizedCollection 类:

RandomizedCollection()初始化空的 RandomizedCollection 对象。
bool insert(int val) 将一个 val 项插入到集合中,即使该项已经存在。如果该项不存在,则返回 true ,否则返回 false 。
bool remove(int val) 如果存在,从集合中移除一个 val 项。如果该项存在,则返回 true ,否则返回 false 。注意,如果 val 在集合中出现多次,我们只删除其中一个。
int getRandom() 从当前的多个元素集合中返回一个随机元素。每个元素被返回的概率与集合中包含的相同值的数量 线性相关 。
您必须实现类的函数,使每个函数的 平均 时间复杂度为 O(1) 。

注意:生成测试用例时,只有在 RandomizedCollection 中 至少有一项 时,才会调用 getRandom 。

示例 1:

输入
[“RandomizedCollection”, “insert”, “insert”, “insert”, “getRandom”, “remove”, “getRandom”]
[[], [1], [1], [2], [], [1], []]
输出
[null, true, false, true, 2, true, 1]

解释
RandomizedCollection collection = new RandomizedCollection();// 初始化一个空的集合。
collection.insert(1); // 返回 true,因为集合不包含 1。
// 将 1 插入到集合中。
collection.insert(1); // 返回 false,因为集合包含 1。
// 将另一个 1 插入到集合中。集合现在包含 [1,1]。
collection.insert(2); // 返回 true,因为集合不包含 2。
// 将 2 插入到集合中。集合现在包含 [1,1,2]。
collection.getRandom(); // getRandom 应当:
// 有 2/3 的概率返回 1,
// 1/3 的概率返回 2。
collection.remove(1); // 返回 true,因为集合包含 1。
// 从集合中移除 1。集合现在包含 [1,2]。
collection.getRandom(); // getRandom 应该返回 1 或 2,两者的可能性相同。

提示:

-231 <= val <= 231 - 1
insert, remove 和 getRandom 最多 总共 被调用 2 * 105
当调用 getRandom 时,数据结构中 至少有一个元素

思路:使用hashmap和list联合操作,hashmap存的是集合的值和该值在list中的索引集合,同时定义一个random类用于后续随机获取,n用于记录list元素个数,调用 RandomizedCollection就是初始化刚才的几个东西,然后插入操作的话就是把值加入到list中,加入到map中同时把索引值加到一个集合中,map存值和值对应得索引集合,n++,最后只需返回该值的索引集合大小是否为1就可以知道是否已经在集合中出现过,对于删除操作,如果map没有相应的key就直接返回false,如果map有相应的key的话就要考虑一个事,因为值是存在了list中,list只有删除最后一个元素是O(1)的,所以我们考虑将要删除的值和最后一个值做交换再删除,要删除map和list两处地方,并且删除完后还要更新最后一个元素的索引集合,更新n,对于随机获取元素操作就直接list.get一个random类生成的n范围内随机数字就好

class RandomizedCollection {Map<Integer,Set> index;List<Integer> list;Random random;int n;public RandomizedCollection() {index = new HashMap<>();list = new ArrayList<>();random = new Random();n = 0;}public boolean insert(int val) {Set set = index.getOrDefault(val, new HashSet<>());//存储索引set.add(n);//存储值list.add(val);index.put(val, set);n++;return set.size() == 1;}public boolean remove(int val) {if(!index.containsKey(val)){return false;}else{//只有移除list中最后一个元素才是O(1)int lastIndex = n - 1;//找到list中最后一个元素的索引集合Set lastset = index.get(list.get(lastIndex));//找到要删除元素的索引集合Set set = index.get(val);//利用迭代器获取要删除元素的一个索引int currentIndex = (int)set.iterator().next();//交换要删除元素和最后一个元素swap(list, currentIndex, lastIndex);//删除最后一个元素list.remove(lastIndex);//删除集合中要删除元素的索引set.remove(currentIndex);if(set.size() == 0){index.remove(val);}//修改变换位置后最后一个值的索引lastset.remove(lastIndex);lastset.add(currentIndex);n--;}return true;}public int getRandom() {return list.get(random.nextInt(n));}public void swap(List<Integer> list, int currentIndex, int lastIndex){int tmp = list.get(currentIndex);list.set(currentIndex, list.get(lastIndex));list.set(lastIndex, tmp); }
}/*** Your RandomizedCollection object will be instantiated and called as such:* RandomizedCollection obj = new RandomizedCollection();* boolean param_1 = obj.insert(val);* boolean param_2 = obj.remove(val);* int param_3 = obj.getRandom();*/

这篇关于力扣381. O(1) 时间插入、删除和获取随机元素 - 允许重复的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/758611

相关文章

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

使用Python实现获取网页指定内容

《使用Python实现获取网页指定内容》在当今互联网时代,网页数据抓取是一项非常重要的技能,本文将带你从零开始学习如何使用Python获取网页中的指定内容,希望对大家有所帮助... 目录引言1. 网页抓取的基本概念2. python中的网页抓取库3. 安装必要的库4. 发送HTTP请求并获取网页内容5. 解

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解