【算法】哈希表
作者:指针不指南吗
专栏:算法篇🐾或许会很慢,但是不可以停下来🐾
文章目录
- 1.定义
- 2.优点
- 3.数字哈希
- 3.1拉链法
- 3.2开放寻址法
- 3.3 例题
- 4.字符串哈希
1.定义
-
哈希表(Hash table),是根据键(Key)直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这样就加快了查找速度。这个映射函数称做散列函数(哈希函数),存放记录的数组称做散列表。
-
就是把一堆庞大数据映射到一个小的数据结构中,比如把0~10910^9109 映射到0~10510^5105 的数组中。
h(x)
一般用x mod n
,n表示数组大小,一般取一个质数,这样冲突出现的概率比较小。 -
冲突:当两个不一样的数,通过哈希函数,映射成一个数的时候,我们无法确定这两个数了,被称为冲突。
2.优点
查找速度快
-
哈希表是种数据结构,它可以提供快速的插入操作和查找操作。
-
不论哈希表中有多少数据,插入和删除,只需要接近常量的时间即 O( 1 ) 的时间复杂度。
哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级。哈希表不仅速度快,编程实现也相对容易。
3.数字哈希
数字哈希是数字到数字的映射关系。
3.1拉链法
-
操作
-
开一个一维数组来存储哈希值;
-
添加值(处理冲突)
-
把每一个数组变量看成是一个槽,在槽上拉一个链,映射
h(x)
出来是对应在槽,即添加在其链上。 -
每条链上的数的个数,期望值是2个
- 整个数组链表大致地样子
- 将一个数插在链表上面
-
-
查找值
映射
h(x)
一下x
,遍历一下,它对应 槽的链上,有没有它 -
删除值
我们不会直接把它删掉,而是定义一个标记
bool
,在对应想要删除的数值上,打一个标记。
-
-
代码实现
- 向哈希表中插入一个数
void insert(int x) {int k=(x%N+N)%N; //哈希(映射)函数,先取模再加N,再取模,是为了保证最后的值是正数e[idex]=x; //插在对应槽的链表里面ne[idex]=h[k];h[k]=idex++; }
- 在哈希表中查询某个数是否存在
bool find(int x) {int k=(x%N+N)%N; //先找出对应的槽for(int i=h[k];i!=-1;i=ne[i]){ //遍历槽的链表,查找是否有相同的值if(e[i]==x) return true;}return false; }
3.2开放寻址法
-
操作
- 只开一个一维数组,数组的大小按经验来说一般是 数据范围的2~3倍;
- 先看一下,对应的槽里有没有数,有数的话,找下一槽,直到找到没有数的槽;
-
代码实现
int h[N]; int null=0x3f3f3f3f; // 如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置 int find(int x) {int k = (x % N + N) % N; //函数映射到槽上while (h[k] != null && h[k] != x) //这个槽里面有数,并且·这个数不是我,循环继续{k ++ ; //找下一个槽if (k == N) k = 0; //如果找到最后了,返回0,继续寻找}return t; }
-
添加元素:
find(x)=x
x不在哈希表里面,find的返回值就是该插入的位置 -
查找元素:
int k = find(x)
如果x不在哈希表中,返回x应该插入的位置,则该位置为空h[k]==null
说明哈希表里面没有这个值 -
删除元素:
和拉链法一样,定义一个bool变量,用作标记
-
3.3 例题
维护一个集合,支持如下几种操作:
I x
,插入一个数 x;Q x
,询问数 x 是否在集合中出现过;现在要进行 N 次操作,对于每个询问操作输出对应的结果。
输入格式
第一行包含整数 N,表示操作数量。
接下来 N 行,每行包含一个操作指令,操作指令为
I x
,Q x
中的一种。输出格式
对于每个询问指令
Q x
,输出一个询问结果,如果 x 在集合中出现过,则输出Yes
,否则输出No
。每个结果占一行。
数据范围
1 ≤ N ≤ 10510^5105
−10910^9109 ≤ x ≤ 10910^9109输入样例:
5 I 1 I 2 I 3 Q 2 Q 5
输出样例:
Yes No
-
方法一:拉链法
#include<bits/stdc++.h>using namespace std;const int N=100003; // N取100010的最大质数,100003 int h[N],ne[N],e[N],idex; //h表示数组中的槽,剩下的表示链表有关 int n;void insert(int x) //添加值的函数 {int k=(x%N+N)%N; //哈希(映射)函数,先取模再加N,再取模,是为了保证最后的值是正数e[idex]=x; //插在对应槽的链表里面ne[idex]=h[k];h[k]=idex++; }bool find(int x) //查找值的函数 {int k=(x%N+N)%N; //先找出对应的槽for(int i=h[k];i!=-1;i=ne[i]){ //遍历槽的链表,查找是否有相同的值if(e[i]==x) return true;}return false; }int main() {scanf("%d",&n ); //读入操作次数memset(h,-1,sizeof h); //清空数组,空指针一般用 -1 表示char op[2]; //读入一个字符的时候,直接用字符数组读入,降低出错率int x; while(n--){scanf("%s%d",op,&x); //读入要操作的类型以及数据if(op[0]=='I') insert(x);else{if(find(x)) puts("Yes");else puts("No");}}return 0; }
-
方法二:开放寻址法
#include<iostream> #include<cstring>using namespace std;const int N=200003,null=0x3f3f3f3f; //N数组长度一般为数据范围的2~3倍且为质数,null表示空指针 int h[N]; //h表示槽的位置 int n;// 如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置 int find(int x) {int k = (x % N + N) % N; //函数映射到槽上while (h[k] != null && h[k] != x) //这个槽里面有数,并且·这个数不是我,循环继续{k ++ ; //找下一个槽if (k == N) k = 0; //如果找到最后了,返回0,继续寻找}return t; }int main() {scanf("%d",&n);memset(h,0x3f,sizeof h);while(n--){char op[2];int x;scanf("%s%d",op,&x);int k=find(x);if(*op=='I') h[k]=x; //往哈希表里面插入元素else{if(h[k]!=null) puts("Yes"); //在哈希表里面寻找元素else puts("No");}}return 0; }
4.字符串哈希
字符串哈希是字符串到数字的映射关系。
我认为这个记住模板就行。
-
映射
- 我们使用的映射关系是字符串到P进制数的映射关系(P是任意的),保证映射是一一对应的,不能有冲突。
- 使冲突最小化,我们取
P=131
或者P=13331
,并且把字符串映射到 2642^{64}264 范围内的数字
-
操作
-
先预处理出来,字符串所有前缀的哈希
防止冲突,不能映射成0。 -
求一段区间的哈希值
-
哈希映射的时候,要对数值取N的模,
unsigned long long
的范围就是2642^{64}264 ,我们可以用它来巧妙地解决取模,因为正好 超过unsigned long long
就会溢出。
-
-
代码模板
typedef unsigned long long ULL; ULL h[N], p[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64// 初始化 p[0] = 1; for (int i = 1; i <= n; i ++ ) {h[i] = h[i - 1] * P + str[i];p[i] = p[i - 1] * P; }// 计算子串 str[l ~ r] 的哈希值 ULL get(int l, int r) {return h[r] - h[l - 1] * p[r - l + 1]; }
-
例题
给定一个长度为 n 的字符串,再给定 m 个询问,每个询问包含四个整数 l1,r1,l2,r2,请你判断 [ l1 , r1 ] 和 [l2,r2]这两个区间所包含的字符串子串是否完全相同。
字符串中只包含大小写英文字母和数字。
输入格式
第一行包含整数 n 和 m,表示字符串长度和询问次数。
第二行包含一个长度为 n 的字符串,字符串中只包含大小写英文字母和数字。
接下来 m 行,每行包含四个整数 l1,r1,l2,r2,表示一次询问所涉及的两个区间。
注意,字符串的位置从 1 开始编号。
输出格式
对于每个询问输出一个结果,如果两个字符串子串完全相同则输出
Yes
,否则输出No
。每个结果占一行。
数据范围
1≤n,m≤10510^5105
输入样例:
8 3 aabbaabb 1 3 5 7 1 3 6 8 1 2 1 2
输出样例:
Yes No Yes
#include<bits/stdc++.h> using namespace std;typedef unsigned long long ULL; //ULL代替取模,映射哈希函数const int N=100010,P=131; ULL p[N],h[N]; //p表示前缀哈希,h表示哈希值int n,m; char str[N];ULL get(int l,int r) //求某段区间的哈希值 {return h[r]-h[l-1]*p[r-l+1]; //右端点的前缀哈希值-左端-1的前缀和哈希值*区间进制 }int main() {scanf("%d%d%s",&n,&m,str+1); //预处理,直接从str+1 开始输入(后面涉及-1操作)p[0]=1; //初始化,因为后面涉及-1和乘法for(int i=1;i<=n;i++){p[i]=p[i-1]*P; //哈希映射,P进制h[i]=h[i-1]*P+str[i]; //前缀哈希值}while(m--){int l1,r1,l2,r2;scanf("%d%d%d%d",&l1,&r1,&l2,&r2);if(get(l1,r1)==get(l2,r2)) puts("Yes"); //区间哈希值相等,则区间的字符相等else puts("No");}return 0; }
之后补充 STL 中哈希表用法
相关文章:
【算法】哈希表
作者:指针不指南吗 专栏:算法篇 🐾或许会很慢,但是不可以停下来🐾 文章目录1.定义2.优点3.数字哈希3.1拉链法3.2开放寻址法3.3 例题4.字符串哈希1.定义 哈希表(Hash table),是根据键…...
彻底搞懂React-hook链表构建原理
写在前面的小结 每一个 hook 函数都有对应的 hook 对象保存状态信息useContext是唯一一个不需要添加到 hook 链表的 hook 函数只有 useEffect、useLayoutEffect 以及 useImperativeHandle 这三个 hook 具有副作用,在 render 阶段需要给函数组件 fiber 添加对应的副…...
【数据挖掘实战】——应用系统负载分析与容量预测(ARIMA模型)
项目地址:Datamining_project: 数据挖掘实战项目代码 目录 一、背景和挖掘目标 1、问题背景 2、传统方法的不足 2、原始数据 3、挖掘目标 二、分析方法与过程 1、初步分析 2、总体流程 第一步:数据抽取 第二步:探索分析 第三步&a…...
【华为OD机试模拟题】用 C++ 实现 - 九宫格按键输入(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明九宫格按键输入题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高…...
Linux: config: CONFIG_SYN_COOKIES
文章目录 CONFIG_SYN_COOKIESLinux kernel里的超时设置Huawei SBC详细工作机制CONFIG_SYN_COOKIES config SYN_COOKIES,布尔值;是否支持IP:TCP syncookie功能。 详解:一般来说TCP/IP网络不能够阻挡SYN flooding工具。这个工具很容易被利用,而且会导致DOS工具,妨碍其他整…...
【笔记】C# 数据类型转换
文章目录前言类型转换的概念1,隐式转换2,显式转换3,程序类转换结语前言 🌻 大家好啊,我是writer桑,本章是关于 C# 数据类型转换的一个总结,其中包含隐式、显示转换和程序类转换,方便…...
JavaWeb JavaBean,MVC三层架构
9、JavaBean 实体类 JavaBean有特定的写法: 必须要有一个无参构造属性必须私有化必须有对应的get/set方法; 一般用来和数据库的字段做映射 ORM; ORM :对象关系映射 表—>类字段–>属性行记录---->对象 people表 …...
JavaEE简单实例——MyBatis一对多关联映射的嵌套结果集查询
简单介绍: 在之前的章节,我们简单介绍了MyBatis中的一对一的关联查询,使用了嵌套查询和嵌套结果集两种方式进行讲解,但是在实际的使用中,我们常用的是嵌套结果集的查询方式,所以在一对多的查询中ÿ…...
大数据框架之Hadoop:MapReduce(三)MapReduce框架原理——OutputFormat数据输出
3.6.1OutputFormat接口实现类 OutputFormat是MapReduce输出的基类,所有实现MapReduce输出都实现了OutputFormat接口。下面我们介绍几种常见的OutputFormat实现类。 1、文本输出TextOutputFormat 默认的输出格式是TextOutputFormat,它把每条记录写为文…...
Linux搜索、编辑
目录 1.搜索 1.1.基础用法 1.2.高级用法 2.编辑 2.1.vim简洁 2.2.vim快捷键 1.搜索 1.1.基础用法 find命令用于搜索,格式如下: find 指定目录 -匹配方式 所要匹配的关键字 所要匹配的关键字支持通配符,?代表一个字符*代表任意个字符。 如果想设…...
Git Commit提交规范总结
文章目录前言git commit 提交规范提交消息头(commit message header)提交消息具体内容(commit message body)提交消息尾述(commit message footer)Revert表情(Emojis)标识idea插件其他操作Commitizen生成 Change logGit获取提交消息格式化输出相关参考前言 我们都知道…...
【ESP 保姆级教程】疯狂毕设篇 —— 案例:基于ESP8266和EMQX的教室灯光控制系统
忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-02-26 ❤️❤️ 本篇更新记录 2022-02-26 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请…...
SpringBoot (一) 项目构建、配置读取、静态资源定义
哈喽,大家好,我是有勇气的牛排(全网同名)🐮 有问题的小伙伴欢迎在文末评论,点赞、收藏是对我最大的支持!!!。 前言 SpringBoot是基于Spring开发的开源项目,…...
<JVM上篇:内存与垃圾回收篇>12 - 垃圾回收相关概念
笔记来源:尚硅谷 JVM 全套教程,百万播放,全网巅峰(宋红康详解 java 虚拟机) 文章目录12.1. System.gc()的理解12.2. 内存溢出与内存泄露内存溢出(OOM)内存泄漏(Memory Leakÿ…...
new操作符做了什么?
new是什么? new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 function Person (name,age) {this.name namethis.age age } Person.prototype.sayName function () {console.log(this.name) } let man new Person(xl,20) consol…...
Java_IO流,书城IO版
1.字符IO流的输入/输出 首先,IO流根据多方面划分。 根据方向划分 输入流/输出流根据处理单元划分 字节流/字符流根据功能划分 节点流/处理流 尝试一下使用字符输入流在读写文件: package IOStream;import java.io.*;public class Test {public stati…...
2023自动化测试岗位需求的 7 项必备技能 (最新版)
目录:导读 一、自动化测试员技能——编程语言 二、自动化测试员技能–出色的手动测试技能 三、.自动化测试员技能–自动化工具专业知识 四、自动化测试员技能–了解业务需求 五、自动化测试员技能–自动化工具故障排除 六、自动化测试员技能–具有测试管理工具…...
【华为OD机试模拟题】用 C++ 实现 - 路灯照明(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明路灯照明【华为OD机试模拟题】题目输入输出描述示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高…...
学到贫血之-贫血模型和充血模型
学习自:设计模式之美 1 基于贫血模型的传统开发模式 // ControllerVO(View Object) public class UserController {private UserService userService; //通过构造函数或者IOC框架注入public UserVo getUserById(Long userId) {UserBo userBo userService.getUser…...
Java常用组件面试题
文章目录HTTP通信协议Kafka消息队列Linux操作系统Mybatis框架SpringCloud框架HTTP通信协议 https通信过程 https协议是指对通过http协议传输数据的进行加密和解密。当客户端发送https请求时,服务端会返回数字证书给客户端,客户端验证通过后会生成随机数…...
MySQL常见问题的解决方法
目录 cmd没有管理员权限 没有my.ini这个文件 ERROR 1045 (28000): Access denied for user ODBClocalhost (using password: NO) ERROR 1045 (28000): Access denied for user rootlocalhost (using password: NO) 其他常见问题 cmd没有管理员权限 cmd一定要用管理员权限打…...
全网详细介绍nginx的反向代理、正向代理配置,location的指令说明,反向代理的两个示例代码以及全局块,events块和http快的说明。
文章目录1. 文章引言2. 何谓反向代理3. 解析nginx的配置文件3.1 全局块(global block)3.2 events块(events block)3.3 http块(http block)4. 如何配置反向代理4.1 反向代理示例14.2 反向代理示例25. 补充说明5.1 location指令说明5.2 nginx完整配置文件1. 文章引言 如果你的服务…...
容斥恒等式的证明
容斥恒等式的证明 推广公式 P(A∪B)P(A)P(B)−P(A∩B)P(A\cup B)P(A)P(B)-P(A\cap B) P(A∪B)P(A)P(B)−P(A∩B) (a)设A、B、C为三个事件,则下列恒等式成立: P(A∪B∪C)P(A)P(B)P(C)−P(A∩B)−P(A∩C)−P(B∩C)P(A∩B∩C)P(A\cup B\cup C)P(A)P(B)P(C)…...
Java中的this与super关键字深度解析
一、this关键字this 关键字是 Java 常用的关键字,可用于任何实例方法内指向当前对象,也可指向对其调用当前方法的对象,或者在需要当前类型对象引用时使用。(1)this.属性名this修饰的变量用于指代成员变量方法的形参如果…...
CSS3新增的视口单位Vh、Vw单位
定义vw:浏览器可见视口【宽度】的百分比(1vw代表视窗【宽度】的1%)vh:浏览器可见视口【高度】的百分比(1vw代表视窗【高度】的1%)vmin:当前 vw 和 vh 较小的一个值。vmax:当前 vw 和…...
【Linux】yum安装docker指定版本
🍁博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 文章目录卸载已有的docker部署指定版本docker安…...
SpringBoot相关操作
01-今日内容 Spring概述、快速入门SpringBoot配置SpringBoot整合 02-SpringBoot概述 SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的…...
Python super()函数:调用父类的构造方法
Python 中子类会继承父类所有的类属性和类方法。严格来说,类的构造方法其实就是实例方法,因此毫无疑问,父类的构造方法,子类同样会继承。 但我们知道,Python 是一门支持多继承的面向对象编程语言,如果子类…...
@ConfigurationProperties在方法上的使用
文章目录1. 前言2. 先说结论3. 代码解释1. Component ConfigurationProperties2. EnableConfigurationProperties ConfigurationProperties3. Bean ConfigurationProperties1. 前言 在学习spring的时候,ConfigurationProperties应该经常被使用到,作用…...
【QT】如何查找和获取界面上的子部件(findChild 和 findChidren)
目录1. findChild()函数2. findChildren()函数3. 示例1. findChild()函数 函数原型: T QObject::findChild(const QString &name QString(), Qt::FindChildOptions options Qt::FindChildrenRecursively) const返回该对象的子对象,该子对象可以转…...
带做骑传奇私服网站/一键建站免费
前言 上篇文章给大家分享了前10个spark的企业面试题2020年最新Spark企业级面试题【上】,今天后续来了,来分享剩下的那个几个面试题。也祝大家找到自己喜欢的工作,一起加油,编写不易 请给老哥一个一键三连吧。 一、手写Spark-Wor…...
新网站建设方案/营销渠道有哪些
Discuz! X3 在继承和完善 Discuz! X2.5 的基础上,针对“系统架构”、“负载性能”、“用户交互体验”等几大方面,进行了全面升级。 为进一步保障正式版的稳定,我们特此发布RC版,希望广大站长协助我们进行测试。 下载地址 简体中…...
wordpress主题背景图片/营销推广有哪些公司
time模块 表示时间有三种表示方式: 时间戳-----time.time(); 格式化的字符串形式 ------time.strftime(); 结构化的元组----time.localtime() time.time(): 时间戳,主要是给计算机看的,从1970年算起到现在过了多少秒; import time…...
面试网站开发员/优化大师win10能用吗
偶尔想在宿舍使用下VCS做些模块,从EETOP上下载了2009.12 MX版本的vcs,在自己vmware (X64) (Ubuntu 2.6.38-8-generic (32bit))下安装一路出现了问题首先:在进行安装时出现失败查找install.log出现如下错误chmod: cannot access var: No such…...
如何进行账号推广/网站优化公司怎么选
Axure RP 8.0 函数对照表axureRP8.0中有很多丰富的函数,这些函数在制作高保真原型时会经常用到,这些函数能够提高我们的工作效率,但一定要注意不要一味地“沉迷”于函数的研究,不要过于纠结某些函数的使用,否则有可能会…...
一品威客网靠谱么/分析网站推广和优化的原因
展开全部/*闲着没事,瞅瞅百度上的问题,今天天晚了,先解决一个,另一个明儿个再说了!第二道题也62616964757a686964616fe4b893e5b19e31333236386266算已经搞定了!环境 : mysql Ver 14.12 Distrib 5.0.45, for…...