问题引入
之前在算法复杂度这一章中提到过,散列算法就是典型用空间换取时间的方法。
什么时间复杂度、空间复杂度,原来不过如此!
具体体现在哪,我们用一个例子来说明。
设分别有两个集合,分别有M个和N个元素。问N个元素中每个数是否在是否在M中出现过。
一个很直观的想法就是:分别输入两组数据,然后用两个for循环来遍历查找。
时间复杂度为O(MN),当N M足够大的时候,显然效率会非常低。
所以我们不妨用空间换取时间,当输入M集合中的数据x的时候,我们都用一个数组hashTable[100010](初始设置为0,默认每个元素都没在这个集合中出现过)来设置hashTable[x] = 1来表明这个数x在M中存在。
这样我们在输入N集合中的数据,直接将输入的这个数作为hashTable数组的下标,就会直接得到我们想要的结果。这是的时间复杂度就降到了O(M+N)。
代码如下:
int m,n,hashTable[10010] = {
0};
cin >>m>>n;
for (int i = 0,x;i<m ;i++ ){
cin>>x;
hashTable[x] = 1;
}
for (int i = 0,x;i<n ;i++ ){
cin>>x;
if(hashTable[x] == 1){
cout<<"YES";
}else{
cout<<"NO";
}
}
在这里,让我们小结一下这里用到的思想:
将输入的数据直接作为数组的下标来记录数据的状态。
这个思想很重要,请小伙伴们一定要掌握。这是个很好的办法,他将查询的复杂度降为了O(1)。
但是这个策略还存在一些问题,上面的问题将输入的数据大小控制在了105 ,但是如果我们输入的数据为大约为109 这么大时,或者甚至是字符串如(“Hello World”)时,就不能直接将他们作为数组下标了。所以我们这时的目标就是将这些数据转化为一个可用的