705. 设计哈希集合

87 阅读2分钟

题目:
不使用任何内建的哈希表库设计一个哈希集合(HashSet)。

实现 MyHashSet 类:

  • void add(key) 向哈希集合中插入值 key
  • bool contains(key) 返回哈希集合中是否存在这个值 key
  • void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。

算法:
方法一:数组法
略。
方法二:位运算
我们用一个int32(int64也可以)表示32个数,每个位上不为0则表示数据存在。数据量10e6 / 32 = 31,250,因此我们最多需要不超过40000个int32。
1.每个int32作为一个bucket,每个bucket内存储32个数。 2.定位bucket的方法:bucketId := num / 32 3.定位buckect内的方法: id := num % 32

type MyHashSet struct {
    bucket []int
}


func Constructor() MyHashSet {
    return MyHashSet{make([]int, 40000)}
}


func (this *MyHashSet) Add(key int)  {
    bocketId := key / 32
    id := key % 32
    this.Set(bocketId, id, true)
}


func (this *MyHashSet) Remove(key int)  {
    bocketId := key / 32
    id := key % 32
    this.Set(bocketId, id, false)
}


func (this *MyHashSet) Contains(key int) bool {
    bocketId := key / 32
    id := key % 32
    return true == this.Exist(bocketId, id)
}

func (this *MyHashSet) Set(bucket, id int, val bool) {
    if val {
        this.bucket[bucket] = this.bucket[bucket] | (1 << id)
    } else {
        this.bucket[bucket] = this.bucket[bucket] & (^(1 << id))
    }
    
}
func (this *MyHashSet) Exist(bucket, id int) bool {
    return this.bucket[bucket] & (1 << id) != 0
}

/**
 * Your MyHashSet object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Add(key);
 * obj.Remove(key);
 * param_3 := obj.Contains(key);
 */

方法三:链表法
链表法本质上是一个二维数组,数据范围1000000,所以平衡地取一个二维数组则是1000 * 1000(避免链表过长或者二维数组长度过长)。我们向上取一个比1000大地质数1009作为二维数组长度。 (为上面要取质数呢?)

type MyHashMap struct {
    List [][][]int
    Len int
}


func Constructor() MyHashMap {
    m :=  MyHashMap{make([][][]int, 1000), 1000}
    return m
}


func (this *MyHashMap) Put(key int, value int)  {
    idx := key % this.Len
    for i, item := range this.List[idx] {
        if item[0] == key {
            this.List[idx][i][1] = value
            return
        }
    }
    this.List[idx] = append(this.List[idx], []int{key, value})
    // fmt.Println(this.List[:5])
}


func (this *MyHashMap) Get(key int) int {
    idx := key % this.Len
    for _, item := range this.List[idx] {
        if item[0] == key {
            return  item[1]
        }
    }
    return -1
}


func (this *MyHashMap) Remove(key int)  {
    idx := key % this.Len
    n := len(this.List[idx])
    i := 0
    exist := false
    for ; i < n; i ++ {
        if this.List[idx][i][0] == key {
            exist = true
            break
        }
    }
    
    // 将要移除的元素交换到数组最后,然后移除数组最后一个元素
    if exist {
        this.List[idx][i], this.List[idx][n - 1] = this.List[idx][n - 1], this.List[idx][i]
        this.List[idx] = this.List[idx][:n - 1]
    }

}