散列要解决的问题
有m个数,要分别知道他们的每一个是否在n个数中出现过,以及出现了多少次,可以用一个整型的散列表来解决这个问题。
- 原始思路:对m个数分别读入,然后在n个数中逐一比对,暴力求解,算法复杂度o(MN)
- 初级思路:读入n个数,以数值大小直接作为下标,建立一个hash表,算法复杂度o(M+N)
- 进阶思路:读入n个元素(不仅局限在数,还可以是字符串等),把他们通过函数转为一个整数,使这个整数尽量唯一代表这个元素,然后用这个整数作为下标,建立hash表
散列的解题思想
用空间换时间
典型应用
给出n个字符串,由三位大写字母组成,再给出m个查询字符串,问每个查询字符串在n个字符串中出现的次数。
#include<cstdio>
using namespace std;
const int maxn = 26 * 26 * 26 + 10;
int hash[maxn] = {0};
int hashFunc(char s[],int len){ //hash函数,将三位字符串转为hash值
int id = 0;
for(int i = 0 ; i < len; i++){
id = id * 26 + (s[i] - 'A');
}
return id;
}
int main()
{
int n,m;
char temp[3];
scanf("%d%d",&n,&m);
for(int i = 0; i < n; i++){
scanf("%s",temp);
hash[hashFunc(temp,3)]++;
}
for(int i = 0; i < m; i++){
scanf("%s",temp);
printf("%d\n",hash[hashFunc(temp,3)]);
}
return 0;
}
扩展方法
在维护hash表时,既可以自定义一个数组,又可以使用C++ STL 的map,可以把map看作扩展的数组,因为不一定要是整型映射到其他类型。
对比: 使用自定义数组往往速度会快一点
leetcode 刷题有感
hash解决的问题有以下特征:
关注一系列元素(或元素进行运算以后)是否出现,有时候还会关注他们出现的次数
- 771 Jewels and Stones
简评:关注石头字符串中出现的宝石字符的个数,本质上是在字符串a中找含于字符串b的字符个数,所以对a建hash表,统计个数,然后根据b找到这些元素累加即可 - 242 Valid Anagram
简评:同素异构体,只要两个字符串中的元素种类和数量都相等即可,所以用其中一个串建表++,用另一串- -即可 - 001 Two Sum
简评:因为要返回的是满足条件的两个元素的下标,所以需要建立hash表保存元素及对应的下标。当然在建表过程中,只要在把当前元素插入之前,检索当前元素的complement是否存在即可。