哈希表题目:设计哈希集合
文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法一
- 思路和算法
- 代码
- 复杂度分析
- 解法二
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:设计哈希集合
出处:705. 设计哈希集合
难度
3 级
题目描述
要求
不使用任何内建的哈希表库设计一个哈希集合。
实现 MyHashSet\texttt{MyHashSet}MyHashSet 类:
- voidadd(key)\texttt{void add(key)}void add(key) 向哈希集合中插入值 key\texttt{key}key。
- boolcontains(key)\texttt{bool contains(key)}bool contains(key) 返回哈希集合中是否存在这个值 key\texttt{key}key。
- voidremove(key)\texttt{void remove(key)}void remove(key) 将给定值 key\texttt{key}key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
示例
示例 1:
输入:
["MyHashSet","add","add","contains","contains","add","contains","remove","contains"]\texttt{["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"]}["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"]
[[],[1],[2],[1],[3],[2],[2],[2],[2]]\texttt{[[], [1], [2], [1], [3], [2], [2], [2], [2]]}[[], [1], [2], [1], [3], [2], [2], [2], [2]]
输出:
[null,null,null,true,false,null,true,null,false]\texttt{[null, null, null, true, false, null, true, null, false]}[null, null, null, true, false, null, true, null, false]
解释:
MyHashSetmyHashSet=newMyHashSet();\texttt{MyHashSet myHashSet = new MyHashSet();}MyHashSet myHashSet = new MyHashSet();
myHashSet.add(1);\texttt{myHashSet.add(1);}myHashSet.add(1); // set=[1]\texttt{set = [1]}set = [1]
myHashSet.add(2);\texttt{myHashSet.add(2);}myHashSet.add(2); // set=[1,2]\texttt{set = [1, 2]}set = [1, 2]
myHashSet.contains(1);\texttt{myHashSet.contains(1);}myHashSet.contains(1); // 返回 True\texttt{True}True
myHashSet.contains(3);\texttt{myHashSet.contains(3);}myHashSet.contains(3); // 返回 False\texttt{False}False(未找到)
myHashSet.add(2);\texttt{myHashSet.add(2);}myHashSet.add(2); // set=[1,2]\texttt{set = [1, 2]}set = [1, 2]
myHashSet.contains(2);\texttt{myHashSet.contains(2);}myHashSet.contains(2); // 返回 True\texttt{True}True
myHashSet.remove(2);\texttt{myHashSet.remove(2);}myHashSet.remove(2); // set=[1]\texttt{set = [1]}set = [1]
myHashSet.contains(2);\texttt{myHashSet.contains(2);}myHashSet.contains(2); // 返回 False\texttt{False}False(已移除)
数据范围
- 0≤key≤106\texttt{0} \le \texttt{key} \le \texttt{10}^\texttt{6}0≤key≤106
- 最多调用 104\texttt{10}^\texttt{4}104 次 add\texttt{add}add、remove\texttt{remove}remove 和 contains\texttt{contains}contains
解法一
思路和算法
由于 key\textit{key}key 的取值范围是 [0,106][0, 10^6][0,106],因此可以创建长度为 106+110^6 + 1106+1 的布尔型数组表示哈希集合,数组中的下标为 key\textit{key}key 的元素值表示 key\textit{key}key 是否在哈希集合中。
构造方法中,将数组初始化为长度 106+110^6 + 1106+1 的数组,并将数组中的全部元素初始化为 false\text{false}false。
对于 add\textit{add}add 操作,将数组中的下标为 key\textit{key}key 的元素设为 true\text{true}true。
对于 contains\textit{contains}contains 操作,返回数组中的下标为 key\textit{key}key 的元素。
对于 remove\textit{remove}remove 操作,将数组中的下标为 key\textit{key}key 的元素设为 false\text{false}false。
需要说明的是,该解法虽然实现简单,但是不适合在面试中使用。
代码
class MyHashSet {boolean[] set;public MyHashSet() {set = new boolean[1000001];Arrays.fill(set, false);}public void add(int key) {set[key] = true;}public void remove(int key) {set[key] = false;}public boolean contains(int key) {return set[key];}
}
复杂度分析
-
时间复杂度:构造方法的时间复杂度是 O(C)O(C)O(C),各项操作的时间复杂度都是 O(1)O(1)O(1),其中 CCC 是 key\textit{key}key 的取值范围的元素个数,这道题中 C=106+1C = 10^6 + 1C=106+1。
构造方法需要创建长度为 CCC 的数组并将每个元素设为初始值,时间复杂度是 O(C)O(C)O(C)。
各项操作只需要对数组中的一个元素赋值或返回元素值,时间复杂度是 O(1)O(1)O(1)。 -
空间复杂度:O(C)O(C)O(C),其中 CCC 是 key\textit{key}key 的取值范围的元素个数,这道题中 C=106+1C = 10^6 + 1C=106+1。需要创建长度为 CCC 的数组表示哈希集合。
解法二
思路和算法
哈希集合的常见实现方法是链表数组,数组的每个下标对应哈希函数可以映射到的索引,当出现哈希冲突时,使用链地址法解决哈希冲突。
用 BASE\textit{BASE}BASE 表示链表数组的长度,则可以使用一个简单的哈希函数:hash(x)=xmodBASE\text{hash}(x) = x \bmod \textit{BASE}hash(x)=xmodBASE,每个键经过哈希函数映射之后的值一定在范围 [0,BASE−1][0, \textit{BASE} - 1][0,BASE−1] 内。为了将哈希函数的值尽可能均匀分布,降低哈希冲突的频率,链表数组的长度应选择质数。此处取链表数组的长度为 101310131013。
构造方法中,将链表数组初始化为长度 BASE\textit{BASE}BASE 的链表数组,并将链表数组中的全部元素初始化为空链表。
对于各项操作,首先计算 key\textit{key}key 对应的哈希值,得到链表数组的下标,根据下标在链表数组中得到相应的链表,然后在链表中执行相应操作。
对于 add\textit{add}add 操作,在链表数组中得到相应的链表之后,遍历链表,如果遇到元素 key\textit{key}key 则不执行任何操作直接返回,如果遍历结束没有遇到元素 key\textit{key}key 则在链表末尾添加元素 key\textit{key}key。
对于 contains\textit{contains}contains 操作,在链表数组中得到相应的链表之后,遍历链表,如果遇到元素 key\textit{key}key 则返回 true\text{true}true,如果遍历结束没有遇到元素 key\textit{key}key 则返回 false\text{false}false。
对于 remove\textit{remove}remove 操作,在链表数组中得到相应的链表之后,遍历链表,如果遇到元素 key\textit{key}key 则将其删除,如果遍历结束没有遇到元素 key\textit{key}key 则不执行任何操作。
实现方面,为了提升运行效率,使用迭代器遍历链表和执行删除操作。
代码
class MyHashSet {private static final int BASE = 1013;private LinkedList<Integer>[] set;public MyHashSet() {set = new LinkedList[BASE];for (int i = 0; i < BASE; i++) {set[i] = new LinkedList<Integer>();}}public void add(int key) {int index = key % BASE;LinkedList<Integer> list = set[index];Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {Integer element = iterator.next();if (element == key) {return;}}list.offerLast(key);}public void remove(int key) {int index = key % BASE;LinkedList<Integer> list = set[index];Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {Integer element = iterator.next();if (element == key) {iterator.remove();break;}}}public boolean contains(int key) {int index = key % BASE;LinkedList<Integer> list = set[index];Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {Integer element = iterator.next();if (element == key) {return true;}}return false;}
}
复杂度分析
-
时间复杂度:构造方法的时间复杂度是 O(BASE)O(\textit{BASE})O(BASE),各项操作的时间复杂度都是 O(nBASE)O\Big(\dfrac{n}{\textit{BASE}}\Big)O(BASEn),其中 nnn 是哈希集合中的元素个数,BASE\textit{BASE}BASE 是链表数组的长度。
构造方法需要创建长度为 BASE\textit{BASE}BASE 的数组并将每个元素设为初始值,时间复杂度是 O(BASE)O(\textit{BASE})O(BASE)。
各项操作需要根据哈希函数计算哈希值,然后遍历链表。计算哈希值需要 O(1)O(1)O(1) 的时间,假设哈希值分布均匀,每个链表的平均长度是 O(nBASE)O\Big(\dfrac{n}{\textit{BASE}}\Big)O(BASEn),因此需要 O(nBASE)O\Big(\dfrac{n}{\textit{BASE}}\Big)O(BASEn) 的时间遍历哈希表。 -
空间复杂度:O(n+BASE)O(n + \textit{BASE})O(n+BASE),其中 nnn 是哈希集合中的元素个数,BASE\textit{BASE}BASE 是链表数组的长度。存储 nnn 个元素需要 O(n)O(n)O(n) 的空间,链表数组需要 O(BASE)O(\textit{BASE})O(BASE) 的空间。
相关文章:
哈希表题目:设计哈希集合
文章目录题目标题和出处难度题目描述要求示例数据范围解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题:设计哈希集合 出处:705. 设计哈希集合 难度 3 级 题目描述 要求 不使用任何内建的哈希表库设计一个哈希…...
java static关键字 万字详解
目录 一、为什么需要static关键字: 二、static关键字概述 : 1.作用 : 2.使用 : 三、static修饰成员变量详解 : 1.特点 : 2.细节 : ①什么时候考虑使用static关键字? ②静态变量和非静态变量的区别? ③关于静态变量的初始化问题 : ④关于静态变…...
光谱实验反射、透射光谱测量
标题反射、透射光谱测量的基本原理 暗背景/基线:Dark………………………………………………………………0% (空)白参考:Reference…………………………………………………………100% 样品反射/透射光谱:Sampl…...
【基础算法】之 冒泡排序优化
冒泡排序思想基本思想: 冒泡排序,类似于水中冒泡,较大的数沉下去,较小的数慢慢冒起来(假设从小到大),即为较大的数慢慢往后排,较小的数慢慢往前排。直观表达,每一趟遍历,…...
Python | 线程锁 | 3分钟掌握【同步锁】(Threading.Lock)
文章目录概念无锁加锁死锁解决死锁概念 threading.Lock 同步锁,可以用于保证多个线程对共享数据的独占访问。 当一个线程获取了锁之后,其他线程在此期间将不能再次获取该锁,直到该线程释放锁。这样就可以保证共享数据的独占访问,…...
Linux下安装MySQL8.0的详细步骤(解压tar.xz安装包方式安装)
Linux下安装MySQL8.0的详细步骤 第一步:下载安装配置 第二步:修改密码,并设置远程连接(为了可以在别的机器下面连接该mysql) 第三步:使用Navicat客户端连接 搞了一台云服务器,首先要干的活就是…...
leaflet 绘制多个点的envelope矩形(082)
第082个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何根据多边形的几个坐标点来绘制envelope矩形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共78行)安装插件相关API参考:专栏目标示例…...
CAJ论文怎么批量免费转换成Word
大家都知道CAJ文件吗?这是中国学术期刊数据库中的文件,这种文件类型比较特殊。如果想要提取其中的内容使用,该如何操作呢?大家可以试试下面这种免费的caj转word的方法,多个文档也可以一起批量转换。准备材料:CAJ文档、…...
面试必问: 结构体大小的计算方法
结构体大小的计算需同时满足以下几点 一、结构体成员的偏移量必须是当前成员大小的整数倍。(0是任何数的整数倍) 举一个例子 struct Test1{char a; // 当前偏移量为0,是char所占字节数1的整数倍 所以所占大小为1char b; …...
Java中super函数的用法
1 问题 Java中super函数有很多方法,在使用的时候我们应该如何正确区分? 2 方法 三种用法: 访问父类的方法。 调用父类构造方法。 访问父类中的隐藏成员变量。 class A{ int x,y; A(int x,int y){ System.out.println("A"); } } cla…...
第十一届“泰迪杯”数据挖掘挑战赛携“十万”大奖火热来袭
第十一届“泰迪杯”数据挖掘挑战赛 竞赛组织 主办单位: 泰迪杯数据挖掘挑战赛组织委员会 承办单位: 广东泰迪智能科技股份有限公司 人民邮电出版社 协办单位: 重庆市工业与应用数学学会、广东省工业与应用数学学会、广西数学学会、河北省工业…...
分享三个可以在家做的正规兼职工作,看到就是赚到
你可以在家做正式的兼职工作。在线兼职工作值得考虑,时间相对自由。在线兼职收入可能不如线下滴滴和外卖立竿见影,但仍然可以坚持收入。有些人比工作工资发展得更高。当然,天上不会有馅饼,不劳无获。那么有哪些正规的兼职可以在家…...
javaFx实现鼠标穿透画布,同时操作画布和桌面,背景透明,类似ppt批注
一、功能需要由来和大致效果 今天,我们要用javaFx来实现一个鼠标穿透画布的功能,该需求来自于在我们的javaFx桌面应用中,需要实现一个悬浮的桌面侧边工具栏,在工具栏中有画笔绘制,批注的功能,能够实现在任何…...
客户服务知识库的最佳实践7个步骤
每个公司的声誉都依赖于客户,如果客户因为想要购买你的产品找到你,但是了解到你的客户服务做的不好,可能也会放弃你的产品,就像市场营销依赖于潜在客户的关系一样,公司的服务部门也需要依赖于现有客户的关系࿰…...
多重继承的虚函数表
同一个类,不同对象使用同一张虚函数表 不同类使用不同的虚函数表 子类自己添加的虚函数(非重写),在VS中是将此放在第一个继承类的虚函数表里. #include <iostream> using namespace std;class Father { public:virtual void func1() { cout << "Father::f…...
第11篇:Java开发工具使用和代码规范配置
目录 1、IntelliJ IDEA 简介 2. IntelliJ IDEA 下载 3. IntelliJ IDEA 安装和使用 3.1 安装到Windows下 3.2 快速编写 Hello World 程序...
Rust模式匹配
模式匹配 模式匹配是从函数式编程语言(例如:Haskell,Lisp)吸收而来的,用于为复杂的类型系统提供一个轻松的解构能力。rust使用match来提供模式匹配的功能。mathc类似于其它编程语言中的switch-case,但是远…...
GIT:【基础一】必要配置和命令
目录 一、Git安装 二、基础命令 1.git config -l:git配置详细信息 2.git config --system -l:本地git系统自动配置的信息 3.git config --global -l:本地git用户自动配置的信息 4.where git: windows查看git安装目录 5.git各配置…...
黑马程序员-Linux系统编程-01
课程链接 01-Linux命令基础习惯-Linux系统编程_哔哩哔哩_bilibili 课程重点笔记 01-linux命令基础习惯 终端 终端:一切输入、输出的总称,因此终端并不是一定指的是命令行,只要是能进行输入或者输出即可,但是在linux终端上‘’内…...
Python|每日一练|动态规划|图算法|散列表|数组|双指针|单选记录:不同路径|求两个给定正整数的最大公约数和最小公倍数|删除有序数组中的重复项
1、不同路径(数学,动态规划) 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”…...
3步解锁音乐自由:NCMDump让NCM格式转换零门槛
3步解锁音乐自由:NCMDump让NCM格式转换零门槛 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 问题破局篇:被囚禁的音乐,你遇到过吗? 你是否经历过这些尴尬场景:下载了喜欢…...
从硬件差异到数据兼容:速腾RS与Velodyne雷达的‘intensity‘字段深度解析
从硬件差异到数据兼容:速腾RS与Velodyne雷达的intensity字段深度解析 激光雷达作为自动驾驶和机器人感知的核心传感器,其数据格式的标准化程度直接影响算法开发的效率。速腾(RoboSense)与Velodyne作为两大主流厂商,硬件…...
【单片机】STM32晶振引脚不连晶振时的做法
STM32不使用外部晶振时,OSC_IN和 OSC_OUT接法:1、对于100脚或者144脚的产品,OSC_IN应接地,OSC_OUT应悬空;2、对于少于100脚的产品,有两种接法:OSC_IN和OSC_OUT分别通过10K电阻接地,此方法可提高…...
Qwen2.5-0.5B-Instruct实战:用Docker快速搭建个人专属AI聊天机器人
Qwen2.5-0.5B-Instruct实战:用Docker快速搭建个人专属AI聊天机器人 1. 引言 你是否想过拥有一个随时待命的AI助手?今天,我们将用最简单的方式,在10分钟内搭建一个属于你自己的智能聊天机器人。Qwen2.5-0.5B-Instruct是阿里开源的…...
云服务器部署大模型
云服务器部署大模型1. 服务器配置2. 大模型下载3. 部署大模型1. 服务器配置 2. 大模型下载 千问2.5-14B-Instruct https://modelscope.cn/models/Qwen/Qwen2.5-14B-Instruct pip install modelscopemodelscope download --model Qwen/Qwen2.5-14B-Instruct --local_dir /root…...
SOA和微服务比较详解
SOA 与微服务架构深度比较 面向服务架构(SOA)和微服务架构(Microservices)都是将系统拆分为可独立部署的服务单元的设计风格,但它们在粒度、通信方式、数据管理、治理、适用场景等方面存在本质差异。系统分析师需要根据业务需求、团队能力和技术栈选择适合的架构。 一、定…...
BililiveRecorder工具箱深度解析:专业级FLV直播录制文件修复解决方案
BililiveRecorder工具箱深度解析:专业级FLV直播录制文件修复解决方案 【免费下载链接】BililiveRecorder 录播姬 | mikufans 生放送录制 项目地址: https://gitcode.com/gh_mirrors/bi/BililiveRecorder BililiveRecorder工具箱提供了一套完整的直播录制文件…...
Swift Core ML Stable Diffusion架构设计:打造高性能移动端AI绘画引擎
Swift Core ML Stable Diffusion架构设计:打造高性能移动端AI绘画引擎 【免费下载链接】swift-coreml-diffusers Swift app demonstrating Core ML Stable Diffusion 项目地址: https://gitcode.com/gh_mirrors/sw/swift-coreml-diffusers 想要在iPhone和Mac…...
Windows热键冲突终极排查指南:3分钟快速定位问题应用
Windows热键冲突终极排查指南:3分钟快速定位问题应用 【免费下载链接】hotkey-detective A small program for investigating stolen key combinations under Windows 7 and later. 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是否曾经…...
3个步骤掌握macOS自动点击器:彻底告别重复鼠标操作的完整方案
3个步骤掌握macOS自动点击器:彻底告别重复鼠标操作的完整方案 【免费下载链接】macos-auto-clicker A simple auto clicker for macOS Big Sur, Monterey, Ventura, Sonoma and Sequoia. 项目地址: https://gitcode.com/gh_mirrors/ma/macos-auto-clicker 你…...
