380.O(1)时间插入、删除和获取随机元素
参考解法:
由于题目要求O(1)内以相等的概率随机返回集合中的一项,因此这道题不能单独使用unordered_set,需要使用数组和哈希表结合的方法。
1.定义一个容量足够大的数组nums,用于存放各个元素val;
2.哈希表my_map的键存放val,值存放val在数组nums中对应的下标;
变量range用于记录元素数目,即数组nums中[0,range]范围的都是有效元素;
my_map[val]是元素val在数组nums中的下标,将哈希表与数组关联起来。
插入元素时:
- 若val已存在于哈希表中,则返回false;
- 否则,将val存入数组nums中,并更新range,在my_map中插入元素val及其下标;
删除元素时:
- 若val不存在,直接返回false;
- 否则,先用pos记录元素val在数组nums中的下标——my_map[val],之后用nums中的末尾元素nums[range]填补待删除元素nums[pos],并更新末尾元素nums[range]在哈希表中的下标值(更新为pos),注意更新range。
使用数组nums来为各个元素绑定一个下标,保证元素分布在numsd的[0,range]下标范围内,从而实现以相同的概率随机访问元素。
const int N = 200000;
int nums[N],range;
class RandomizedSet {
public:
RandomizedSet() {
range = -1;
}
bool insert(int val) {
if(!my_map.count(val)){
nums[++range] = val;
my_map[val] = range;
return true;
}
return false;
}
bool remove(int val) {
if(my_map.count(val)){
int pos = my_map[val];
my_map.erase(val);
if(pos != range) my_map[nums[range]] = pos;
nums[pos] = nums[range--];
return true;
}
return false;
}
int getRandom() {
return nums[rand() % (range + 1)];
}
private:
unordered_map<int,int> my_map;
};