Design a data structure that supports all following operations in average O(1) time.

  1. insert(val): Inserts an item val to the set if not already present.
  2. remove(val): Removes an item val from the set if present.
  3. getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.

Example:

// Init an empty set.
RandomizedSet randomSet = new RandomizedSet(); // Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomSet.insert(1); // Returns false as 2 does not exist in the set.
randomSet.remove(2); // Inserts 2 to the set, returns true. Set now contains [1,2].
randomSet.insert(2); // getRandom should return either 1 or 2 randomly.
randomSet.getRandom(); // Removes 1 from the set, returns true. Set now contains [2].
randomSet.remove(1); // 2 was already in the set, so return false.
randomSet.insert(2); // Since 1 is the only number in the set, getRandom always return 1.
randomSet.getRandom();

这道题让我们在常数时间范围内实现插入删除和获得随机数操作,如果这道题没有常数时间的限制,那么将会是一道非常简单的题,直接用一个 HashSet 就可以搞定所有的操作。但是由于时间的限制,无法在常数时间内实现获取随机数,所以只能另辟蹊径。此题的正确解法是利用到了一个一维数组和一个 HashMap,其中数组用来保存数字,HashMap 用来建立每个数字和其在数组中的位置之间的映射,对于插入操作,先看这个数字是否已经在 HashMap 中存在,如果存在的话直接返回 false,不存在的话,将其插入到数组的末尾,然后建立数字和其位置的映射。删除操作是比较 tricky 的,还是要先判断其是否在 HashMap 里,如果没有,直接返回 false。由于 HashMap 的删除是常数时间的,而数组并不是,为了使数组删除也能常数级,实际上将要删除的数字和数组的最后一个数字调换个位置,然后修改对应的 HashMap 中的值,这样只需要删除数组的最后一个元素即可,保证了常数时间内的删除。而返回随机数对于数组来说就很简单了,只要随机生成一个位置,返回该位置上的数字即可,参见代码如下:

class RandomizedSet {
public:
RandomizedSet() {}
bool insert(int val) {
if (m.count(val)) return false;
nums.push_back(val);
m[val] = nums.size() - ;
return true;
}
bool remove(int val) {
if (!m.count(val)) return false;
int last = nums.back();
m[last] = m[val];
nums[m[val]] = last;
nums.pop_back();
m.erase(val);
return true;
}
int getRandom() {
return nums[rand() % nums.size()];
}
private:
vector<int> nums;
unordered_map<int, int> m;
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/380

类似题目:

Insert Delete GetRandom O(1) - Duplicates allowed

参考资料:

https://leetcode.com/problems/insert-delete-getrandom-o1/

https://leetcode.com/problems/insert-delete-getrandom-o1/discuss/85422/AC-C%2B%2B-Solution.-Unordered_map-%2B-Vector

https://leetcode.com/problems/insert-delete-getrandom-o1/discuss/85401/Java-solution-using-a-HashMap-and-an-ArrayList-along-with-a-follow-up.-(131-ms)

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 380. Insert Delete GetRandom O(1) 常数时间内插入删除和获得随机数的更多相关文章

  1. [LeetCode] Insert Delete GetRandom O(1) 常数时间内插入删除和获得随机数

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

  2. [leetcode]380. Insert Delete GetRandom O(1)常数时间插入删除取随机值

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

  3. [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 ...

  4. LeetCode 380. Insert Delete GetRandom O(1) 常数时间插入、删除和获取随机元素(C++/Java)

    题目: Design a data structure that supports all following operations in averageO(1) time. insert(val): ...

  5. [LeetCode] 380. Insert Delete GetRandom O(1) 插入删除获得随机数O(1)时间

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

  6. LeetCode 380. Insert Delete GetRandom O(1)

    380. Insert Delete GetRandom O(1) Add to List Description Submission Solutions Total Accepted: 21771 ...

  7. 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). ...

  8. [LeetCode] Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  9. [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 ...

随机推荐

  1. Linux高性能服务器编程,书中的 shell 命令

    记录<Linux高性能服务器编程>书里面讲解到的若干 shell 命令 arp 命令查看ARP高速缓存: [root@VM_0_10_centos heliang]# arp -a ? ( ...

  2. 十一、Spring之事件监听

    Spring之事件监听 ApplicationListener ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成Applica ...

  3. linux jconsole的远程配置--实测可用

    工作上,经常要对tomcat的java内存配置.tomcat线程池等进行调(luan)优(gao). jconsole 是一个最基础用到的jdk自带的JVM性能查看工具. 最近进行linux测试. 所 ...

  4. 安利一波ubuntu18.04作为开发环境,极度舒适

    乌班图18更新也一年多了吧,除了最开始的尝鲜,最近才真正使用起来.用完的感受是完爆Windows,比起OSX也不差. 开发环境需要的东西: git shell idea chrome firefox ...

  5. 【论文阅读】Objects as Points 又名 CenterNet | 目标检测

    目录 Abstract Instruction 分析 CenterNet 的Loss公式 第一部分:\(L_k\) 第二部分:\(L_{size}\) 第三部分:\(L_{off}\) Abstrac ...

  6. WPF xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

    <Button Grid.Row="1" Content="Load Data" BorderBrush="Black" Border ...

  7. 以STM32和FPGA为核心的多组件协调工作系统

  8. 安装使用 superset

    安装 superset 创建虚拟环境: python -m venv msuperset 激活虚拟环境: cd msuperset source bin/activate 安装 superset pi ...

  9. Android App压力测试方法(Monkey)

    一.为什么要开展压力测试 a.提高产品的稳定性:b.提高产品的留存率 二.什么时候开展压力测试 a.首轮功能测试通过后:b.下班后的夜间进行 三.7个基础知识(理论部分) 3.1 手动测试场景与自动测 ...

  10. Spring Boot MVC 使用 JSP 作为模板

    Spring Boot 默认使用 Thymeleaf 作为模板引擎,直接在 template 目录中存放 JSP 文件并不能正常访问,需要在 main 目录下新建一个文件夹来存放 JSP 文件,而且需 ...