力扣 705. 设计哈希集合 哈希(链式地址法) 位运算实现哈希

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 vectorforward_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,2641],一个 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);
 */

猜你喜欢

转载自blog.csdn.net/xiji333/article/details/114718907