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 ...
 
随机推荐
- DEVOPS技术实践_07:Jenkins 管道工作
			
一 简介 由于在公司构建很多工作,都是使用的maven工作构建的,这种构建方式很大缺点就是所有的工作都需要一步一步的配置,当项目较多,需求变动时,需要很大的精力去修改配置,很费劲 Pipeline即为 ...
 - 【题解】P5446 [THUPC2018]绿绿和串串(manacher)
			
[题解]P5446 [THUPC2018]绿绿和串串(manacher) 考虑对于一个串进行\(f\)操作,就是让他变成一个以最后一个节点为回文中心的回文串. 那么对于某个位置\(p\),假如它是一个 ...
 - 洛谷$P3959\ [NOIp2017]$ 宝藏 状压$dp$
			
正解:状压$dp$ 解题报告: 传送门$QwQ$ $8102$年的时候就想搞这题了,,,$9102$了$gql$终于开始做这题了$kk$ 发现有意义的状态只有当前选的点集和深度,所以设$f_{i,j} ...
 - SpringDataJpa多条件查询代码封装
			
package com.pantech.cloud.mlogistics.util; import com.mysql.jdbc.StringUtils; import org.springframe ...
 - POJ1144 Network 题解 点双连通分量(求割点数量)
			
题目链接:http://poj.org/problem?id=1144 题目大意:给以一个无向图,求割点数量. 这道题目的输入和我们一般见到的不太一样. 它首先输入 \(N\)(\(\lt 100\) ...
 - 使用Eureka中遇到的一些问题
			
1.情况 : 服务已经注册到eureka,eureka中可以看到,但是 consumer和provider这两个服务,一直报错, 错误信息:DiscoveryClient_CONSUMER-DEM ...
 - MySQL数据库用户、角色、授权
			
权限包括 insert delete update select all privileges 登录MySQL > mysql -uroot -p Enter password ...
 - 2D地图擦除算法
			
. 关于2D地图擦除算法,去年我写过一个实现,勉强实现了地形擦除,但跟最终效果还相差甚远,这次我写了一个完整的实现,在此记录,留个印象. . 去年的版本<<算法 & 数据结构--裁 ...
 - Manacher 学习
			
推荐博客 :https://blog.csdn.net/zzkksunboy/article/details/72600679 作用 线性时间解决最长回文子串问题. 思想 Manacher充分利用了回 ...
 - 引用dll出现的问题:发生一个或多个错误,引用无效或不支持该引用
			
获取到新的项目后,然后FineUI就出现黄色的标志,肯定是不可以用的,需要重新引用下. 然后我就开始重新引用下,就出现下面的问题: 因为是购买的UI,一开始我怀疑是引用的版本不一样呢,其实都不是 只需 ...