LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复(C++/Java)
题目:
Design a data structure that supports all following operations in averageO(1) time.
Note: Duplicate elements are allowed.
insert(val): Inserts an item val to the collection.remove(val): Removes an item val from the collection if present.getRandom: Returns a random element from current collection of elements. The probability of each element being returned is linearly related to the number of same value the collection contains.
Example:
// Init an empty collection.
RandomizedCollection collection = new RandomizedCollection(); // Inserts 1 to the collection. Returns true as the collection did not contain 1.
collection.insert(1); // Inserts another 1 to the collection. Returns false as the collection contained 1. Collection now contains [1,1].
collection.insert(1); // Inserts 2 to the collection, returns true. Collection now contains [1,1,2].
collection.insert(2); // getRandom should return 1 with the probability 2/3, and returns 2 with the probability 1/3.
collection.getRandom(); // Removes 1 from the collection, returns true. Collection now contains [1,2].
collection.remove(1); // getRandom should return 1 and 2 both equally likely.
collection.getRandom();
分析:
这道题是leetcode380的进阶版,也就是允许出现重复的元素。这里附上380的题解LeetCode 380. Insert Delete GetRandom O(1) 常数时间插入、删除和获取随机元素(C++/Java)。
同样使用HashMap来支持插入和移除操作,利用数组来支持对数据的随机访问。只不过hashmap中val对应的是一个存放该元素在数组中索引的数组,当删除操作时,可以快速定位到该元素在数组的位置。
而数组中不只存放val,而是将val和该val在hashmap中对应的数组的索引,用来支持
我们来配合例子看一下:
依次执行
insert(1);insert(1);insert(2);
此时存储的情况如图:

此时我们执行remove(1)的操作,我们首先通过map找到1这个元素对应的数组,取出数组中最后一个元素,表示的便是1这个元素在Array数组中的索引。

由于数组删除最后一个元素的时间复杂度为O(1)(不考虑扩容这种情况),我们将要删除的位置和数组中最后一个元素置换,或者是覆盖都可以。
然后我们再根据当前位置的这个元素去修改Map中数据,Array中元素的第二个值表示这个val在map中val对应的数组中的索引,此时我们要修改这个索引的值,改为array中调整后的索引值。最后在将无用的数据删除掉即可。


说着确实有些繁琐,不过通过实例配合图片过一遍应该比较好理解!
程序:
C++
class RandomizedCollection {
public:
/** Initialize your data structure here. */
RandomizedCollection() {
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val) {
m[val].push_back(v.size());
v.emplace_back(val, m[val].size() - );
return true;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val) {
if(!m.count(val))
return false;
int lIndex = m[val].back();
auto entry = v.back();
v[lIndex] = entry;
m[entry.first][entry.second] = lIndex;
v.pop_back();
m[val].pop_back();
if(m[val].empty())
m.erase(val);
return true;
}
/** Get a random element from the collection. */
int getRandom() {
int index = rand() % v.size();
return v[index].first;
}
private:
unordered_map<int, vector<int>> m;
vector<pair<int, int>> v;
};
Java
class RandomizedCollection {
/** Initialize your data structure here. */
public RandomizedCollection() {
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
public boolean insert(int val) {
List<Integer> l = map.getOrDefault(val, new ArrayList<Integer>());
l.add(list.size());
map.put(val, l);
list.add(new Pair<>(val, l.size()-1));
return true;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
public boolean remove(int val) {
if(!map.containsKey(val))
return false;
List<Integer> l = map.get(val);
int lastIndex = l.get(l.size()-1);
Pair<Integer, Integer> p = list.get(list.size()-1);
list.set(lastIndex, p);
List<Integer> cl = map.get(p.getKey());
cl.set(p.getValue(), lastIndex);
map.put(p.getKey(), cl);
list.remove(list.size()-1);
l.remove(l.size()-1);
if(l.size() == 0)
map.remove(val);
return true;
}
/** Get a random element from the collection. */
public int getRandom() {
Random r = new Random();
int index = r.nextInt(list.size());
return list.get(index).getKey();
}
private HashMap<Integer, List> map = new HashMap<>();
private ArrayList<Pair<Integer, Integer>> list = new ArrayList<>();
}
LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复(C++/Java)的更多相关文章
- 381 Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复
设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构.注意: 允许出现重复元素. insert(val):向集合中插入元素 val. remove(val):当 val ...
- [LeetCode] 381. Insert Delete GetRandom O(1) - Duplicates allowed 插入删除和获得随机数O(1)时间 - 允许重复
Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...
- [LeetCode] 381. Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复
Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...
- LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed
原题链接在这里:https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/?tab=Description ...
- LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed (插入删除和获得随机数 常数时间 允许重复项)
Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...
- [leetcode]381. Insert Delete GetRandom O(1) - Duplicates allowed常数时间插入删除取随机值
Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...
- leetcode 380. Insert Delete GetRandom O(1) 、381. Insert Delete GetRandom O(1) - Duplicates allowed
380. Insert Delete GetRandom O(1) 实现插入.删除.获得随机数功能,且时间复杂度都在O(1).实际上在插入.删除两个功能中都包含了查找功能,当然查找也必须是O(1). ...
- 381. Insert Delete GetRandom O(1) - Duplicates allowed
Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...
- 381. Insert Delete GetRandom O(1) - Duplicates allowed允许重复的设计1数据结构
[抄题]: Design a data structure that supports all following operations in average O(1) time. Note: Dup ...
随机推荐
- The second day of Crawler learning
用BeatuifulSoup和Requests爬取猫途鹰网 服务器与本地的交换机制 我们每次浏览网页都是再向网页所在的服务器发送一个Request,然后服务器接受到Request后返回Response ...
- linux 更新jdk
1.上传jdk版本的包 下载JDK地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.h ...
- Mysql 最全查询语句
基本查询语句及语法: select distinct from where group by having limit 一.单表查询 前期表与数据准备: # 创建一张部门表 create table ...
- 洛谷$P2168\ [NOI2015]$荷马史诗 贪心
正解:贪心 解题报告: 传送门$QwQ$ 昂这个就哈夫曼树板子题鸭$QwQ$,只是从二叉变成多叉了$QwQ$ 考虑用类似合并果子的方法?就从两个变成$k$个了嘛,一样的鸭,然后就做完了$QwQ$ 注意 ...
- Linux下卸载oracle需要删除的文件
卸载oracle需要删除的文件 rm -rf /data1/oracle/app #oracle安装目录在/data1/oracle中 rm -rf /usr/local/bin/dbhome rm ...
- [技术翻译]Web网页内容是如何影响电池使用寿命的?
本周再来翻译一些技术文章,本次预计翻译三篇文章如下: 04.[译]使用Nuxt生成静态网站(Generate Static Websites with Nuxt) 05.[译]Web网页内容是如何影响 ...
- 手把手带你了解消息中间件(3)——RocketMQ
一.RocketMQ简介 RocketMQ作为一款纯java.分布式.队列模型的开源消息中间件,支持事务消息.顺序消息.批量消息.定时消息.消息回溯等. 二.RocketMQ架构 如图所示为R ...
- Go Web 编程之 程序结构
概述 一个典型的 Go Web 程序结构如下,摘自<Go Web 编程>: 客户端发送请求: 服务器中的多路复用器收到请求: 多路复用器根据请求的 URL 找到注册的处理器,将请求交由处理 ...
- Netty快速入门(03)Java NIO 介绍-Buffer
NIO 介绍 NIO,可以说是New IO,也可以说是non-blocking IO,具体怎么解释都可以. NIO 1是在JSR51里面定义的,在JDK1.4中引入,因为BolckingIO不支持高并 ...
- MariaDB的备份与主从、高可用实践
1.编写脚本,支持让用户自主选择,使用mysqldump还是xtraback全量备份. [root@test-centos7-node1 scripts]# cat chose_backup_mysq ...