leetcode链接:O(1) 时间插入、删除和获取随机元素 - 允许重复
题目描述
设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构。
注意: 允许出现重复元素。
insert(val):向集合中插入元素 val。
remove(val):当 val 存在时,从集合中移除一个 val。
getRandom:从现有集合中随机获取一个元素。每个元素被返回的概率应该与其在集合中的数量呈线性相关。
API设计和调用示例
// 初始化一个空的集合。
RandomizedCollection collection = new RandomizedCollection();
// 向集合中插入 1 。返回 true 表示集合不包含 1 。
collection.insert(1);
// 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
collection.insert(1);
// 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
collection.insert(2);
// getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
collection.getRandom();
// 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
collection.remove(1);
// getRandom 应有相同概率返回 1 和 2 。
collection.getRandom();
/**
* 调用示例如下:
* RandomizedCollection* obj = new RandomizedCollection();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
思路分析
我们使用一个数组存储所有可能的数。当添加数时,把它放到尾部就行了;对于删除数,因为我们要实现O(1)
,而对于数组,只有删除最后一个元素才是O(1)
,因此我们不妨让最后一个元素和要删除的元素进行替换,删除最后一个元素即可。由删除操作可知,我们要找到删除元素的位置,为了实现O(1)
,我们用一个哈希表记录数字在数组中的位置。随机取数就用random()
函数%
数组大小。
详细过程见代码:
class RandomizedSet {
public:
vector<int> nums;
unordered_map<int,int> numIndex;
int size;
/** Initialize your data structure here. */
RandomizedSet() {
size = 0;
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val) {
if(numIndex.count(val) == 1) return false; //不能重复插入数字
nums.push_back(val);
numIndex[val] = size;
size++;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val) {
if(numIndex.count(val) == 0) return false;
int last = nums.back();
nums[numIndex[val]] = last;
numIndex[last] = numIndex[val]; //删除的数和最后一个数进行替换
nums.pop_back();
numIndex.erase(val);
size--;
return true;
}
/** Get a random element from the set. */
int getRandom() {
return nums[random() % size];
}
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/