散列
散列简单来说:给N个正整数和M个负整数,问这M个数中的每个数是否在N中出现过。
比如:N:{1,2,3,4},M{2,5,7},其中M的2在N中出现过
对这个问题最直观的思路是:对M中每个欲查的值x,都在N中遍历一次,时间复杂度为 O(NM),但当N和M的值很大时,显然无法承受
所以,我们可以设定一个bool型数据 hashTable[100010],其中hashTable[x]== true 表示正整数x在N个正整数中出现过,而hashTable[x]= false表示正整数x在N个正整数中没有出现过。这样就可以在一开始读入N个正整数时就进行预处理,即当读入的数为x时,就令hashTable[x] = true (说明: hashTable 数组需要初始化为false,表示初始状态下所有数都未出现过)。 于是,对M个欲查询的数,就能直接通过hashTable数组判断出每个数是否出现过。显然这种做法的时间复杂度为O(N+M),代码如下:
#include<cstdio>
const int maxn=1; //见注1 //maxn的值可以取大于0的任意数
bool hashTable[maxn]={false}; //见注2
int main()
{int n,m,x;printf("输入n m的值\n"); scanf("%d%d",&n,&m); //输入nm两个数组各自的长度for(int i=0;i<n;i++){printf("输入第一组参照的第%d个x的值\n",i+1); scanf("%d",&x); //键盘输入n的数据hashTable[x]=true; }for(int i=0;i<m;i++){ printf("输入第二组的第%d个值\n",i+1); scanf("%d",&x); //键盘输入m的数据if(hashTable[x]==true) //判断数据相同{printf("yes\n"); //相同则返回yes,否则返回no}elseprintf("no\n");}
}
注1:/* const 允许指定一个语义约束,编译器会强制实
施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,
就应该明确使用const,这样可以获得编译器的帮助。 即const是使这个值固定不再改变*/
注2:bool类型 为逻辑型,它的值只有true(1)和false(0)两种值。
空间换时间,定义一个bool型数组hashTable[100010],其中hashTable[x]==true表示正整数x在N个正整数中出现过。这样就可以在一开始读入N个正整数的时候就进行预处理。
同样的,如果题目要求M个欲查询的数中每个数在N个数中出现的次数,那么可以把nastTable数组替换为int型,然后在输入N个数时进行预处理,即当输入的数为x时,就令nhashTable[x]++,这样就可以用O(N + M)的时间复杂度输出每个欲查询的数出现的次数。代码如下:
#include<cstdio>
const int maxn=1; /* const 允许指定一个语义约束,编译器会强制实
施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,
就应该明确使用const,这样可以获得编译器的帮助。*/
bool hashTable[maxn]={false};
int main()
{int n,m,x;printf("输入n m的值\n"); scanf("%d%d",&n,&m);for(int i=0;i<n;i++){printf("输入第一组参照的第%d个x的值\n",i+1); scanf("%d",&x);hashTable[x]=true; }for(int i=0;i<m;i++){ printf("输入第二组的第%d个值\n",i+1); scanf("%d",&x);if(hashTable[x]==true){printf("yes\n");}elseprintf("no\n");}
}