力扣-705. 設計雜湊集合

DawnTraveler發表於2024-05-03

1.題目

題目地址(705. 設計雜湊集合 - 力扣(LeetCode))

https://leetcode.cn/problems/design-hashset/

題目描述

不使用任何內建的雜湊表庫設計一個雜湊集合(HashSet)。

實現 MyHashSet 類:

  • void add(key) 向雜湊集合中插入值 key
  • bool contains(key) 返回雜湊集合中是否存在這個值 key
  • void remove(key) 將給定值 key 從雜湊集合中刪除。如果雜湊集合中沒有這個值,什麼也不做。

示例:

輸入:
["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"]
[[], [1], [2], [1], [3], [2], [2], [2], [2]]
輸出:
[null, null, null, true, false, null, true, null, false]

解釋:
MyHashSet myHashSet = new MyHashSet();
myHashSet.add(1);      // set = [1]
myHashSet.add(2);      // set = [1, 2]
myHashSet.contains(1); // 返回 True
myHashSet.contains(3); // 返回 False ,(未找到)
myHashSet.add(2);      // set = [1, 2]
myHashSet.contains(2); // 返回 True
myHashSet.remove(2);   // set = [1]
myHashSet.contains(2); // 返回 False ,(已移除)

提示:

  • 0 <= key <= 106
  • 最多呼叫 104addremovecontains

2.題解

2.1 設計雜湊對映

思路

這裡主要解釋下為何儘可能使用素數作為雜湊集合/表的大小
參考:雜湊表的大小為何最好是素數
參考:演算法分析:雜湊表的大小為何是素數

主要是因為很多數列都是間隔固定的週期性數列,儲存這些數列時,發生雜湊衝突的可能性和我們雜湊集合的大小的因子數量成正比
如果待儲存的數列間隔恰好是是被取模數的因子大小,那麼合數要比素數更容易呈現週期性的取模重複。

程式碼

  • 語言支援:C++

C++ Code:

class MyHashSet {
private:
    vector<list<int>> data;
    static const int base = 769; // 只有static const 變數才能在類內初始化, 只有static是不可的,需要類外初始化
    static int Hash(int key) { return key % base; }

public:
    MyHashSet() : data(base) {}

    void add(int key) {
        int n = Hash(key);
        for (int num : data[n]) {
            if (num == key)
                return;
        }
        data[n].push_back(key);
    }

    void remove(int key) {
        int n = Hash(key);
        for (auto it = data[n].begin(); it != data[n].end(); it++) {
            if (*it == key) {
                data[n].erase(it);
                return; // 這裡要注意,我們如果刪除當前迭代器指向的物件後,不能再使用該迭代器, 否則會報 heap-use-after-free 的錯誤
            }
        }
    }

    bool contains(int key) {
        int n = Hash(key);
        for (int num : data[n]) {
            if (num == key)
                return true;
        }
        return false;
    }
};

/**
 * 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);
 */

複雜度分析

令 n 為陣列長度。

  • 時間複雜度:\(O(n)\)
  • 空間複雜度:\(O(n)\)

相關文章