https://leetcode-cn.com/problems/design-hashset/
思路一:朴实无华且枯燥的链地址法,通过
v
e
c
t
o
r
、
f
o
r
w
a
r
d
_
l
i
s
t
vector、forward\_list
vector、forward_list实现(后者是一个单向链表)。
class MyHashSet {
public:
/** Initialize your data structure here. */
const int num=2333;
vector<forward_list<int>> hashTable;
MyHashSet() {
hashTable.resize(num);
}
void add(int key) {
if(!contains(key))
hashTable[key%num].push_front(key);
}
void remove(int key) {
int idx=key%num;
forward_list<int>::iterator it=hashTable[idx].before_begin();
forward_list<int>::iterator nxt=hashTable[idx].begin();
forward_list<int>::iterator ed=hashTable[idx].end();
while(nxt!=ed&&*nxt!=key)
it=nxt++;
if(nxt!=ed)
hashTable[idx].erase_after(it);
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
int idx=key%num;
forward_list<int>::iterator it=hashTable[idx].begin();
forward_list<int>::iterator ed=hashTable[idx].end();
while(it!=ed&&*it!=key)
++it;
return it!=ed;
}
};
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet* obj = new MyHashSet();
* obj->add(key);
* obj->remove(key);
* bool param_3 = obj->contains(key);
*/
思路二:位运算实现哈希,这个思想相当巧妙。考虑用一个 u n s i g n e d l o n g l o n g unsigned\ long\ long unsigned long long数组实现哈希,不妨设模数为 b a s e base base,那么对于任意 k e y key key,我们可以把它转换为两部分: ⌊ k e y / b a s e ⌋ \lfloor key/base \rfloor ⌊key/base⌋和 k e y % b a s e key\%base key%base,第一部分决定它在数组中的下标,第二部分决定它在该处值的二进制表示的第几位(这里看代码应该更加直观)。考虑到 u l l ull ull类型的取值范围为 [ 0 , 2 64 − 1 ] [0,2^{64}-1] [0,264−1],一个 u l l ull ull类型最多对应64个数值,所以应取 b a s e = 64 base=64 base=64,数组的范围应该为 ⌊ m a x _ k e y / b a s e ⌋ + 1 \lfloor max\_key/base \rfloor+1 ⌊max_key/base⌋+1。
class MyHashSet {
public:
/** Initialize your data structure here. */
const int base=64;
vector<unsigned long long> hashTable;
MyHashSet() {
int max=1e6,num=max/base;
if(num*base==max)
++num;
hashTable.resize(num);
}
void add(int key) {
hashTable[key/base]|=1ull<<(key%base);
}
void remove(int key) {
hashTable[key/base]&=~(1ull<<(key%base));
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
return hashTable[key/base]&(1ull<<(key%base));
}
};
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet* obj = new MyHashSet();
* obj->add(key);
* obj->remove(key);
* bool param_3 = obj->contains(key);
*/