首先知道rand() % n 表示从[0, n - 1]中出一个随机数,在windows下rand()的范围是33767, 在Linux下会到108级别,可以随机很大的数
这一题要做到在时间复杂度为O(1)的情况,插入要求我们用到哈希表,返回O(1)则需要使用数组,这题需要哈希表和数组结合,如果插入的没有重复元素,很简单:
vector<int> nums;
unordered_map<int,int>hash;
建立val 与 nums下标的映射关系即可;
但是有重复元素的情况下,如果使用multimap,显然不行,因为不支持索引,所以需要在哈希表嵌套哈希表,hash[x]里面装着nums[] 相同val(若有)的不同下标:
unordered_map<int, unordered_set<int>>hash;
注意我们使用删除函数的时候,需要在哈希表里面删除这个元素,同时,也要在数组里面删除这个元素,数组里面删除,我们只需要把这个val,和数组中的最后一个元素nums[nums.szie() - 1]调换一下,并且在哈希表里面交换一下两个数的索引,再nums.pop_back(),才可以将val排除,避免数组内部出现空缺。
最后就是返回随机数,看代码就行:
class RandomizedCollection {
public:
unordered_map<int, unordered_set<int>>hash;
vector<int>nums;
RandomizedCollection() {
}
bool insert(int x) {
if (hash[x].size() == 0) {
nums.push_back(x);
hash[x].insert(nums.size() - 1);
return true;
}
else {
nums.push_back(x);
hash[x].insert(nums.size() - 1);
return false;
}
}
bool remove(int x) {
if (hash[x].size()) {
int y = nums.back();
int px = *hash[x].begin(), py = nums.size() - 1; //解引用,表示对一个 unondered_set<int>的对象里面的第一个迭代器位置进行解引用,得到的就是x在nums[]里的一个下标
hash[x].erase(px); hash[x].insert(py); // 交换索引
hash[y].erase(py); hash[y].insert(px);
swap(nums[px], nums[py]);
hash[x].erase(py);
nums.pop_back();
return true;
}
else return false;
}
int getRandom() {
return nums[rand() % nums.size()]; //返回随机数
}
};
/**
* 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();
*/