当前位置: 首页 > news >正文

哈希表题目:设计哈希集合

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:设计哈希集合

出处: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}0key106
  • 最多调用 104\texttt{10}^\texttt{4}104add\texttt{add}addremove\texttt{remove}removecontains\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),其中 CCCkey\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),其中 CCCkey\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,BASE1] 内。为了将哈希函数的值尽可能均匀分布,降低哈希冲突的频率,链表数组的长度应选择质数。此处取链表数组的长度为 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) 的空间。

相关文章:

哈希表题目:设计哈希集合

文章目录题目标题和出处难度题目描述要求示例数据范围解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题&#xff1a;设计哈希集合 出处&#xff1a;705. 设计哈希集合 难度 3 级 题目描述 要求 不使用任何内建的哈希表库设计一个哈希…...

java static关键字 万字详解

目录 一、为什么需要static关键字&#xff1a; 二、static关键字概述 : 1.作用 : 2.使用 : 三、static修饰成员变量详解 : 1.特点 : 2.细节 : ①什么时候考虑使用static关键字? ②静态变量和非静态变量的区别&#xff1f; ③关于静态变量的初始化问题 : ④关于静态变…...

光谱实验反射、透射光谱测量

标题反射、透射光谱测量的基本原理  暗背景/基线&#xff1a;Dark………………………………………………………………0%  &#xff08;空&#xff09;白参考&#xff1a;Reference…………………………………………………………100%  样品反射/透射光谱&#xff1a;Sampl…...

【基础算法】之 冒泡排序优化

冒泡排序思想基本思想: 冒泡排序&#xff0c;类似于水中冒泡&#xff0c;较大的数沉下去&#xff0c;较小的数慢慢冒起来&#xff08;假设从小到大&#xff09;&#xff0c;即为较大的数慢慢往后排&#xff0c;较小的数慢慢往前排。直观表达&#xff0c;每一趟遍历&#xff0c;…...

Python | 线程锁 | 3分钟掌握【同步锁】(Threading.Lock)

文章目录概念无锁加锁死锁解决死锁概念 threading.Lock 同步锁&#xff0c;可以用于保证多个线程对共享数据的独占访问。 当一个线程获取了锁之后&#xff0c;其他线程在此期间将不能再次获取该锁&#xff0c;直到该线程释放锁。这样就可以保证共享数据的独占访问&#xff0c…...

Linux下安装MySQL8.0的详细步骤(解压tar.xz安装包方式安装)

Linux下安装MySQL8.0的详细步骤 第一步&#xff1a;下载安装配置 第二步&#xff1a;修改密码&#xff0c;并设置远程连接&#xff08;为了可以在别的机器下面连接该mysql&#xff09; 第三步&#xff1a;使用Navicat客户端连接 搞了一台云服务器&#xff0c;首先要干的活就是…...

leaflet 绘制多个点的envelope矩形(082)

第082个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何根据多边形的几个坐标点来绘制envelope矩形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共78行)安装插件相关API参考:专栏目标示例…...

CAJ论文怎么批量免费转换成Word

大家都知道CAJ文件吗&#xff1f;这是中国学术期刊数据库中的文件&#xff0c;这种文件类型比较特殊。如果想要提取其中的内容使用&#xff0c;该如何操作呢&#xff1f;大家可以试试下面这种免费的caj转word的方法,多个文档也可以一起批量转换。准备材料&#xff1a;CAJ文档、…...

面试必问: 结构体大小的计算方法

结构体大小的计算需同时满足以下几点 一、结构体成员的偏移量必须是当前成员大小的整数倍。&#xff08;0是任何数的整数倍&#xff09; 举一个例子 struct Test1{char a; // 当前偏移量为0&#xff0c;是char所占字节数1的整数倍 所以所占大小为1char b; …...

Java中super函数的用法

1 问题 Java中super函数有很多方法&#xff0c;在使用的时候我们应该如何正确区分&#xff1f; 2 方法 三种用法&#xff1a; 访问父类的方法。 调用父类构造方法。 访问父类中的隐藏成员变量。 class A{ int x,y; A(int x,int y){ System.out.println("A"); } } cla…...

第十一届“泰迪杯”数据挖掘挑战赛携“十万”大奖火热来袭

第十一届“泰迪杯”数据挖掘挑战赛 竞赛组织 主办单位&#xff1a; 泰迪杯数据挖掘挑战赛组织委员会 承办单位&#xff1a; 广东泰迪智能科技股份有限公司 人民邮电出版社 协办单位&#xff1a; 重庆市工业与应用数学学会、广东省工业与应用数学学会、广西数学学会、河北省工业…...

分享三个可以在家做的正规兼职工作,看到就是赚到

你可以在家做正式的兼职工作。在线兼职工作值得考虑&#xff0c;时间相对自由。在线兼职收入可能不如线下滴滴和外卖立竿见影&#xff0c;但仍然可以坚持收入。有些人比工作工资发展得更高。当然&#xff0c;天上不会有馅饼&#xff0c;不劳无获。那么有哪些正规的兼职可以在家…...

javaFx实现鼠标穿透画布,同时操作画布和桌面,背景透明,类似ppt批注

一、功能需要由来和大致效果 今天&#xff0c;我们要用javaFx来实现一个鼠标穿透画布的功能&#xff0c;该需求来自于在我们的javaFx桌面应用中&#xff0c;需要实现一个悬浮的桌面侧边工具栏&#xff0c;在工具栏中有画笔绘制&#xff0c;批注的功能&#xff0c;能够实现在任何…...

客户服务知识库的最佳实践7个步骤

每个公司的声誉都依赖于客户&#xff0c;如果客户因为想要购买你的产品找到你&#xff0c;但是了解到你的客户服务做的不好&#xff0c;可能也会放弃你的产品&#xff0c;就像市场营销依赖于潜在客户的关系一样&#xff0c;公司的服务部门也需要依赖于现有客户的关系&#xff0…...

多重继承的虚函数表

同一个类,不同对象使用同一张虚函数表 不同类使用不同的虚函数表 子类自己添加的虚函数(非重写),在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模式匹配

模式匹配 模式匹配是从函数式编程语言&#xff08;例如&#xff1a;Haskell&#xff0c;Lisp&#xff09;吸收而来的&#xff0c;用于为复杂的类型系统提供一个轻松的解构能力。rust使用match来提供模式匹配的功能。mathc类似于其它编程语言中的switch-case&#xff0c;但是远…...

GIT:【基础一】必要配置和命令

目录 一、Git安装 二、基础命令 1.git config -l&#xff1a;git配置详细信息 2.git config --system -l&#xff1a;本地git系统自动配置的信息 3.git config --global -l&#xff1a;本地git用户自动配置的信息 4.where git&#xff1a; windows查看git安装目录 5.git各配置…...

黑马程序员-Linux系统编程-01

课程链接 01-Linux命令基础习惯-Linux系统编程_哔哩哔哩_bilibili 课程重点笔记 01-linux命令基础习惯 终端 终端&#xff1a;一切输入、输出的总称&#xff0c;因此终端并不是一定指的是命令行&#xff0c;只要是能进行输入或者输出即可&#xff0c;但是在linux终端上‘’内…...

Python|每日一练|动态规划|图算法|散列表|数组|双指针|单选记录:不同路径|求两个给定正整数的最大公约数和最小公倍数|删除有序数组中的重复项

1、不同路径&#xff08;数学&#xff0c;动态规划&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

高抗扰度汽车光耦合器的特性

晶台光电推出的125℃光耦合器系列产品&#xff08;包括KL357NU、KL3H7U和KL817U&#xff09;&#xff0c;专为高温环境下的汽车应用设计&#xff0c;具备以下核心优势和技术特点&#xff1a; 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计&#xff0c;确保在…...

算法250609 高精度

加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...