【题目】实现RandomizedSet
类:
RandomizedSet()
初始化RandomizedSet
对象bool insert(int val)
当元素val
不存在时,向集合中插入该项,并返回true
;否则,返回false
。bool remove(int val)
当元素val
存在时,从集合中移除该项,并返回true
;否则,返回false
。int getRandom()
随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。
你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1)
。
示例:
输入 ["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"] [[], [1], [2], [2], [], [1], [2], []] 输出 [null, true, false, true, 2, true, false, 2] 解释 RandomizedSet randomizedSet = new RandomizedSet(); randomizedSet.insert(1); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。 randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。 randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。 randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。 randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。 randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。 randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
【思路】本题不难看出,难点为O(1)复杂度来构造方法。总体方法思路为先设置一个vector和一个unordered_map容器,然后用map容器存储对应元素及其位置,用vector数组来记录所有元素。
如果是insert方法的话,则先在map中查询,如果没有则加入,加入的方式为用map记录存储的下标,并在数组末尾添加此元素;
如果是remove方法,则先查询,如果存在的话,则将数组最后一个元素与将删除元素换位置,然后释放map对应元素,数组弹出末尾元素。
解题思路巧妙的点在于通过unordered_map既能找到元素对应数组下标,又能判断元素是否存在于数组中。
【insert代码】
bool insert(int val) {
if(mymap.count(val)){//查询出现次数null or 1
return false;
}else{
int len = nums.size();
nums.emplace_back(val); //将元素加入到数组末尾
mymap[val] = len; //存储元素下标
return true;
}
}
【remove代码】
bool remove(int val) {
if(!mymap.count(val)){
return false;
}else{
//交换数组移除元素与末尾元素位置
int position = mymap[val];
int last_num = nums.back();
//更新之前末尾元素的下标
nums[position]=last_num;
mymap[last_num]=position;
//释放map
mymap.erase(val);
//弹出数组末尾元素
nums.pop_back();
return true;
}
}
【getrandom代码】
int getRandom() {
int addr = rand()%nums.size(); //随机生成数字与数组大小模运算
return nums[addr];
}
【完整代码】
class RandomizedSet {
public:
RandomizedSet() {}
bool insert(int val) {
if(mymap.count(val)){
return false;
}else{
int len = nums.size();
nums.emplace_back(val);
mymap[val] = len;
return true;
}
}
bool remove(int val) {
if(!mymap.count(val)){
return false;
}else{
int position = mymap[val];
int last_num = nums.back();
nums[position]=last_num;
mymap[last_num]=position;
mymap.erase(val);
nums.pop_back();
return true;
}
}
int getRandom() {
int addr = rand()%nums.size();
return nums[addr];
}
private:
unordered_map<int,int>mymap;
vector<int>nums;
};
【总结】起初并没有完全看懂题意,通过在网站上查询解法,然后加上自己补充,将代码诠释出来,如果有更好解法,欢迎在评论下方发表哦。