705. Design HashSet
仅供自己学习
思路:
主要还是去重和冲突的解决。
可以直接开个很大的数组直接存放即可,用下标代表为什么数,该位置的值用0和1来判断是否存放了。
还有一种的散列表,如果这个位置存放了那就+1,+2这样找到下一个没有冲突的位置
还有一个就是每个数组的位置都有一个链表。
如果使用链表,对于数组的大小我们使用一个固定长度,且为质数,原因是:
查了下质数取模,其实是利用了同余的感念:当元素是个有规律的等差数列时,并且和基数(数组大小)最大公约数不为1时,就会造成哈希映射时冲突变高(数组某些位置永远不会有值)。比如数列0,6,12,18,24...,
- base为10,取模放入哈希表中位置将只能在0,2,4,6,8这几个数组位置上
- 但我们如果把base取7(数组大小甚至比10小),同样数列可以分布在哈希表中的0,1,2,3,4,5,6
可以使得哈希表中每个位置都“有用武之地”
然后其他功能每个都要用key值mod数组的固定长度后得到的数就是存放数组的哪个位置,然后遍历该位置的链表,对于add,如果没有相同的元素,那么就直接加载后面,对于remove如果发现有就erase,对于contain如果有就返回true
代码:
1 class MyHashSet { 2 private: 3 vector<list<int>> data; 4 static const int base=769; 5 static int hash(int key){ 6 return key%base; 7 } 8 public: 9 /** Initialize your data structure here. */ 10 MyHashSet(): data(base){} 11 12 void add(int key) { 13 int h=hash(key); 14 for(auto a=data[h].begin();a!=data[h].end();++a){ 15 if(*a==key) 16 return; 17 } 18 data[h].push_back(key); 19 } 20 21 void remove(int key) { 22 int h=hash(key); 23 for(auto a=data[h].begin();a!=data[h].end();++a){ 24 if(*a==key){ 25 data[h].erase(a); 26 return; 27 } 28 } 29 } 30 31 /** Returns true if this set contains the specified element */ 32 bool contains(int key) { 33 int h=hash(key); 34 for(auto a=data[h].begin();a!=data[h].end();++a){ 35 if(*a==key) 36 return true; 37 } 38 return false; 39 } 40 }; 41 42 /** 43 * Your MyHashSet object will be instantiated and called as such: 44 * MyHashSet* obj = new MyHashSet(); 45 * obj->add(key); 46 * obj->remove(key); 47 * bool param_3 = obj->contains(key); 48 */

浙公网安备 33010602011771号