O(1) 时间插入、删除和获取随机元素

实现RandomizedSet 类:

  • RandomizedSet() 初始化 RandomizedSet 对象
  • bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false
  • bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false
  • int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。

你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1)


要求常数时间下插入和删除元素所以考虑哈希表。随机返回集合中的一项也就是可以对集合随机访问,但是哈希表不能做到这点,所以还要引入顺序表来支持随机访问。

这个题的处理方式很像静态链表,就是用数组构建的链表,链表在空间上是连续的。

设置哈希表hash<元素值,下标>,动态数组aa的下标对应hash的下标,a的元素值对应hash的元素值。

对应关系稍微有点绕,写了两遍才完全搞明白。


总结一下unordered_mapvector的常用函数,经常容易忘,每次都要现查。

size() 返回容量
empty() 容器为空返回true,否则返回true
find(key)//哈希表 若找到,返回对应迭代器,否则返回最后一个元素后一个位置的迭代器
begin() 返回第一个元素/键值对的迭代器
end() 返回最后一个位置后一个位置的迭代器
back()//vector 返回vector的最后一个元素
count(key)//哈希表 返回key的个数
push_back(x)//vector 插入x
pop_back()//vector 删除最后一个元素
erase(key)//哈希表 清除key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class RandomizedSet {
private:
vector<int> a;
unordered_map<int,int> hash;
public:
RandomizedSet() {

}

bool insert(int val) {
if(!hash.count(val)){
hash[val]=a.size();
a.push_back(val);
return true;
}
return false;
}

bool remove(int val) {
if(hash.count(val)){
int last = a.back();
int index=hash[val];
a[hash[val]]=a.back();
a[hash[a.back()]]=val;
hash[last]=index;
a.pop_back();
hash.erase(val);
return true;
}
return false;
}

int getRandom() {
return a[rand()%a.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();
*/