设计哈希集合 & 解决哈希冲突的三种方法

在这里插入图片描述

https://leetcode-cn.com/problems/design-hashset/solution/she-ji-ha-xi-ji-he-by-leetcode/

概述

LC705这是教科书上一个经典问题,用来测试一个人的数据结构知识。因此,是不可以用任何内置的 HashSet 数据结构来解决此问题。

为了实现 HashSet 数据结构,有两个关键的问题,即哈希函数和冲突处理。

  • 哈希函数:目的是分配一个地址存储值。理想情况下,每个值都应该有一个对应唯一的散列值。
  • 冲突处理:哈希函数的本质就是从 A 映射到 B。但是多个 A 值可能映射到相同的 B。这就是碰撞。因此,我们需要有对应的策略来解决碰撞。总的来说,有以下几种策略解决冲突:
    1. 单独链接法:对于相同的散列值,我们将它们放到一个桶中,每个桶是相互独立的。
    2. 开放地址法:每当有碰撞, 则根据我们探查的策略找到一个空的槽为止。
    3. 双散列法:使用两个哈希函数计算散列值,选择碰撞更少的地址。
      在本文中,我们使用单独链接法,来看看它是如何工作的。

从本质上讲,HashSet 的存储空间相当于连续内存数组。这个数组中的每个元素相当于一个桶。
给定一个值,我们首先通过哈希函数生成对应的散列值来定位桶的位置。
一旦找到桶的位置,则在该桶上做相对应的操作,如 add,remove,contains。

方法一:单独链表法

哈希函数的共同特点是使用模运算符。hash=value mod base。其中,base 将决定 HashSet 中的桶数。

从理论上讲,桶越多(因此空间会越大)越不太可能发生碰撞。base 的选择是空间和碰撞之间的权衡。

此外,使用质数作为 base 是一个明智的选择。例如 769,可以减少潜在的碰撞。
在这里插入图片描述
对于桶的设计,我们有几种选择,可以使用数组来存储桶的所有值。然而数组的一个缺点是需要 O(N) 的时间复杂度进行插入和删除,而不是 O(1)

因为任何的更新操作,我们首先是需要扫描整个桶为了避免重复。选择链表来存储桶的所有值是更好的选择,插入和删除具有常数的时间复杂度。

1.1单独链接法算法:

正如我们在上面讨论的,这里将采用 LinkedList 实现 HashSet 中的桶。

对于每个功能 add,remove,contains,我们首先生成桶的散列值,操作相对应的桶。

class MyHashSet {
   
  private Bucket[] bucketArray;
  private int keyRange;

  /** Initialize your data structure here. */
  public MyHashSet() {
   
    this.keyRange = 769;
    this.bucketArray = new Bucket[this.keyRange];
    for (int i = 0; i < this.keyRange; ++i)
      this.bucketArray[i] = new Bucket();
  }

  protected int _hash(int key) {
   
    return (key % this.keyRange);
  }

  public void add(int key) {
   
    int bucketIndex = this._hash(key);
    this.bucketArray[bucketIndex].insert(key);
  }

  public void remove(int key) {
   
    int bucketIndex = this._hash(key);
    this.bucketArray[bucketIndex].delete(key);
  }

  /** Returns true if this set contains 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值