一、题目
二、分析
这个题,可以从两个维度考虑,节省时间 or 节省空间。
- 如果想要极致的时间,可以用
vector<bool>
大小为 1 0 6 10^6 106,表示每个数的存在与否。时间复杂度 O ( 1 ) O(1) O(1),但是空间复杂度 O ( n ) O(n) O(n)。 - 对于这种大范围整数,可以采用
bitmap
来存储,以压缩存储空间。不了解的看这里:https://www.jianshu.com/p/6082a2f7df8e - 我这里采用类似的方式去做。如下:有一个
vector
大小为 1 0 6 / 8 + 1 = 125001 10^6/8 + 1 = 125001 106/8+1=125001,因为每个int值存储8个数的有无。比如图中的vec[0]=5
,其二进制为0000 0101
则表示哈希表中有0, 2
。
- 判断元素有无
比如判断表中有没有key = 12,
1. 首先要确定12位于第几个vec: key / 8 (1);
2. 还要判断vec[key/8]中有没有12对应的偏移,即key % 8 (4)处是否为1;
只需要将vec[key/8] 与1 << key % 8 进行按位与。
1001 0000 & 0001 0000 = 0001 0000, 如果不为0,则表示hash表中有该元素。
- 插入元素,先判断有无(不再解释,只解释插入)
比如插入一个key = 9.
1. 首先要判断插入到第几个vec: key / 8 (1);
2. 确认插入到哪个偏移处:即key % 8 (1)处;
那么只需要将vec[key/8] 加上 1 << key % 8;
1001 0000 + 0000 0010 =1001 0010
(vec[1] = 144 + 2 = 146)
- 删除元素,先判断有无
比如删除一个key = 9.
1. 首先要判断要删除的key在第几个vec: key / 8 (1);
2. 确认位于哪个偏移处:即key % 8 (1)处;
那么只需要将vec[key/8] 减去 1 << key % 8;
1001 0010 - 0000 0010 =1001 0000
(vec[1] = 146 - 2 = 144)
三、代码
class MyHashSet {
private:
vector<int> vec;
public:
/** Initialize your data structure here. */
MyHashSet() {
vec.resize(125001);
}
void add(int key) {
if(!contains(key))
vec[key / 8] += 1 << (key % 8);
}
void remove(int key) {
if(contains(key))
vec[key / 8] -= 1 << (key % 8);
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
return vec[key / 8] & (1 << key % 8);
}
};
执行用时:96 ms, 在所有 C++ 提交中击败了87.96%的用户
内存消耗:55.5 MB, 在所有 C++ 提交中击败了21.79%的用户