散列(hash)-----基础版
散列可以表示为一句话:将元素通过一个函数转换为整数,使得该整数可以尽量唯一地代表这个元素!
来看一个简单的问题:给出N个正整数,再给出M个正整数,问M个数中的每个数分别是否在N个数中出现过,其中N,M<=105,且所有正整数均不超过105。
例子:N=5,M=3,N个正整数为{8,2,4,7,1},M个正整数为{7,4,9},于是后者中7、4在N个正整数中出现过,而9是没有出现过。
较为简单的思路:遍历所有N个正整数,看是否一个数与所要查询的正整数x相等。这种方法的时间复杂度为O(NM),当N和M都很大的时候(105),显然无法承受的!
因此想到用空间换时间。设定一个bool数组hashTable[100010],其中hashTable[x] == true表示正整数x在N个正整数中出现过,否则,没有出现过。如此,我们就可以在一开始读入N个正整数时就可以进行预处理,即当读入的数为x时,就令hashTable[x] == true(hashTable数组初始化为false)。这种方法的时间复杂度为O(N+M)!
代码:
#include <cstdio> const int maxn = 100010; bool hashTable[maxn] = {false}; int main() { int n,m,x; scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%d",&x); hashTable[x] = true; } for(int i=0;i<m;i++){ scanf("%d",&x); if(hashTable[x] == true) printf("YES\n"); else printf("NO\n"); } return 0; }
如果题目需要M个待查询的数中每个数在N个数中出现的次数,那么就可以将hashTable换成int型,然后在输入N个正整数时进行处理,即每当输入x时,就令hashTable[x]++,这种方法只需要O(N+M)的时间复杂度输出每个预查询的数出现的次数。
上面两个问题的特点:直接把输入的数作为数组的下标来对这个数组的性质进行统计!(此方法非常实用,多练习掌握)
有关散列函数内容以及解决冲突的办法,都在数据结构学科内,可以找本数据结构书籍进行学习!
字符串hash问题
字符串hansh是将一个字符串S映射为一个整数,使得该整数可以尽可能唯一地代表字符串S!
如果字符串中出现了大写、小写字母,可以把A~Z作为0~25,把a~z作为26~51,这样就变成了五十二进制转换为十进制的问题。由进制转换的结论可知,在进制转换的过程中,得到的十进制肯定是唯一的,因此就可以实现将字符串映射为整数的需求(注意:转换的整数最大为26len-1,其中len为字符串的长度)。
代码:
int hashFunc(char S[],int len){ int id = 0; for(int i=0;i<len;i++){ if(S[i] >= 'A' && S[i] <='Z') id = id*52+(S[i] - 'A'); else if(S[i] >= 'a' && s[i] <= 'z') id = id*52+(S[i] - 'a' + 26); } return id; }
但有时候字符串中间会出现数字,而对于数字,有以下两种处理方式:
1.和上面的小写字母的处理方法一样,在进制数后面再添加十位就可以,这里就是增大进制数至62;
2.有的题目可能是直接确定在字符串后面是确定个数的数字,那么此时的处理方法可以是前面的英文字母按照上述思路转换为整数,而末尾的数字直接拼接上去就好。举个例子:对于由三个字符加上末尾是一位数字组成的字符串“BCD4”来讲,可以先将前面的“BCD”转换为整数731,然后直接将数字4拼接上去成为7314即可。
代码:
int hashFunc(char S[],int len){ int id = 0; for(int i=0;i<len;i++){ if(S[i] >= 'A' && S[i] <='Z') id = id*52+(S[i] - 'A'); else if(S[i] >= 'a' && s[i] <= 'z') id = id*52+(S[i] - 'a' + 26); else id = id*10+(S[i] - '0'); } return id; }
习题练习:
给出N个字符串(由恰好三个大写字母拼成),再给出M个查询字符串,问每个查询字符串在N个字符串中出现的次数。
代码:
#include <cstdio> const int maxn = 100; char S[maxn][5],temp[5]; int hashTable[26*26*26+10]; int hashFunc(char S[],int len){ int id = 0; for(int i=0;i<len;i++){ if(S[i] >= 'A' && S[i] <='Z') id = id*52+(S[i] - 'A'); } return id; } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ sacnf("%d",&S[i]); int id = hashFunc(S[i],3); hashTable[id]++; } for(int i=0;i<n;i++){ scanf("%s",temp); int id = hashFunc(temp,3); printf("%d\n",hashTable[i]): } return 0; }
hash进阶版:https://www.cnblogs.com/techgy/p/15039772.html
__EOF__

本文链接:https://www.cnblogs.com/techgy/p/15037113.html
关于博主:I am a good person
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~