Leetcode 381. Insert Delete GetRandom O(1) - Duplicates allowed (数据结构设计好题)

  1. Insert Delete GetRandom O(1) - Duplicates allowed
    Hard

RandomizedCollection is a data structure that contains a collection of numbers, possibly duplicates (i.e., a multiset). It should support inserting and removing specific elements and also reporting a random element.

Implement the RandomizedCollection class:

RandomizedCollection() Initializes the empty RandomizedCollection object.

bool insert(int val) Inserts an item val into the multiset, even if the item is already present. Returns true if the item is not present, false otherwise.

bool remove(int val) Removes an item val from the multiset if present. Returns true if the item is present, false otherwise. Note that if val has multiple occurrences in the multiset, we only remove one of them.

int getRandom() Returns a random element from the current multiset of elements. The probability of each element being returned is linearly related to the number of the same values the multiset contains.

You must implement the functions of the class such that each function works on average O(1) time complexity.

Note: The test cases are generated such that getRandom will only be called if there is at least one item in the RandomizedCollection.

Example 1:

Input

["RandomizedCollection", "insert", "insert", "insert", "getRandom", "remove", "getRandom"]

[[], [1], [1], [2], [], [1], []]

Output

[null, true, false, true, 2, true, 1]

Explanation

RandomizedCollection randomizedCollection = new RandomizedCollection();

randomizedCollection.insert(1); // return true since the collection does not contain 1.

// Inserts 1 into the collection.

randomizedCollection.insert(1); // return false since the collection contains 1.

// Inserts another 1 into the collection. Collection now contains [1,1].

randomizedCollection.insert(2); // return true since the collection does not contain 2.

// Inserts 2 into the collection. Collection now contains [1,1,2].

randomizedCollection.getRandom(); // getRandom should:

// - return 1 with probability 2/3, or

// - return 2 with probability 1/3.

randomizedCollection.remove(1); // return true since the collection contains 1.

// Removes 1 from the collection. Collection now contains [1,2].

randomizedCollection.getRandom(); // getRandom should return 1 or 2, both equally likely.

Constraints:

-231 <= val <= 231 - 1

At most 2 * 105 calls in total will be made to insert, remove, and getRandom.

There will be at least one element in the data structure when getRandom is called.

解法1:注意题目的要求。每个操作(insert(), delete(), getRandom())都必须是O(1)时间复杂度。

getRandom()是O(1),那么必须用数组。

insert()和delete()是O(1),可以用doubly linked list+map,也可以直接就用unordered_set()。

cpp 复制代码
class RandomizedCollection {
public:
    RandomizedCollection() {
    }
    
    bool insert(int val) {
        bool res = false;
        if (val2freq.find(val) == val2freq.end()) res = true;
        val2freq[val]++;
        data.push_back(val);
        val2index[val].insert(data.size() - 1);
        return res;
    }
    
    bool remove(int val) {
        if (val2freq.find(val) == val2freq.end()) {
            return false;
        }
        int remove_elem_index = *val2index[val].begin();
        int last_elem = data.back();
        if (last_elem != val) {
            val2index[last_elem].erase(data.size() - 1);
            val2index[last_elem].insert(remove_elem_index);
            val2index[val].erase(remove_elem_index);
            data[remove_elem_index] = last_elem;
        }
        data.pop_back();
        val2freq[val]--;
        if (val2freq[val] == 0) {
            val2freq.erase(val);
            val2index.erase(val);
        }
        return true;
    }
    
    int getRandom() {
        return data[random() % data.size()];
    }
private:
    unordered_map<int, int> val2freq; //<value, freq>
    //unordered_map<int, vector<int>> val2index; //<value, indexes>
    unordered_map<int, unordered_set<int>> val2index; //<value, indexes>
    vector<int> data;    
};

/**
 * Your RandomizedCollection object will be instantiated and called as such:
 * RandomizedCollection* obj = new RandomizedCollection();
 * bool param_1 = obj->insert(val);
 * bool param_2 = obj->remove(val);
 * int param_3 = obj->getRandom();
 */
相关推荐
ZSYP-S5 分钟前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos12 分钟前
C++----------函数的调用机制
java·c++·算法
唐叔在学习17 分钟前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA36 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo38 分钟前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
jackiendsc1 小时前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法
姚先生971 小时前
LeetCode 54. 螺旋矩阵 (C++实现)
c++·leetcode·矩阵
游是水里的游2 小时前
【算法day20】回溯:子集与全排列问题
算法
yoyobravery2 小时前
c语言大一期末复习
c语言·开发语言·算法
Jiude2 小时前
算法题题解记录——双变量问题的 “枚举右,维护左”
python·算法·面试