散列
例:给出N个正整数,再给出M个正整数,问这M个数中的每个数分别是否在N个数中出现过
思路一:对每个要查询的正整数x,遍历所有n个数,看是否有一个数与x相等
思路二:用空间换时间,设定一个bool型数组hashTable,其中hashTable[x]==true表示正整数x在N个正整数中出现过,而hashTable[x]==false表示正整数x在N个正整数中没有出现过,这样就可以在一开始读入N个正整数时就进行预处理,即当读入的数为x时,就令hashTable[x]=true,于是对M个欲查询的数,直接通过hashTable数组判断出每个数是否出现过,时间复杂度为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)的时间复杂度输入每个与查询的数出现的次数,代码:
#include<iostream> const int maxn=100010; int hashTable[maxn]={0}; int main(){ int n,m,x; scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%d",&x); hashTable[x]++; } for(int i=0;i<m;i++){ scanf("%d",&x); printf("%d\n",hashTable[x]); } return 0; }
例题:给出N个字符串,再给出M个查询字符串,问每个查询字符串在N个字符串中出现的次数
#include<iostream> using namespace std; 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++){ id=id*26+(S[i]-'A'); } return id; } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%s",S[i]); int id=hashFunc(S[i],3); hashTable[id]++; } for(int i=0;i<m;i++){ scanf("%s",temp); int id=hashFunc(temp,3); printf("%d\n",hashTable[id]); } return 0; }