散列的定义与整数散列

散列的定义与整数散列
先来看一个简单的问题:给出N个正整数,再给出M个正整数,问这M个数中的每个数分别是否在N个数中出现过,其中N,M≤10 5,且所有正整数均不超过10 5。例如N=5,M=3,N个正整数为{8,3,7,6,2},欲查询的M个正整数为{7,4,2},于是后者中只有7和2在N个正整数中出现过,而4是没有出现过的。对这个问题,最直观的思路是:对每个欲查询的正整数x,遍历所有N个数,看是否有个数与x相等。这种做法的时间复杂度为O(NM),当N和M都很大(10 5级别)时,显然是无法承受的。

那么该如何做呢?ー一不妨用空间换时间,即设定一个bool型数组 hashTable[100010]其中 hashTable[x]=true表示正整数x在N个正整数中出现过,而 hash Table[x]= false表示正整数x在N个正整数中没有出现过。这样就可以在一开始读入N个正整数时就进行预处理,即当读入的数为x时,就令 hashtable x]=tnue(说明:hash Table数组需要初始化为 false,表示初始状态下所有数都未出现过)。于是,对M个欲查询的数,就能直接通过 hash Table数组
判断出每个数是否出现过。显然这种做法的时间复杂度为O(N+M),代码如下:

include <cstdio>
const int maxn a 100010;
bool hashtable[maxi ]={false}:
int main( ){
	int n, m, x;
	scanf("dd",&n,&m);
	for(int1=0:1<n:1++)
	scanf("%d", &x):
	hashTable [x]=true;//数字x出现过
	}
	for(int1=0;1<m;1++)
		scanf("%d",&x)
		if( hashtable[x]==true)(//如果数字x出现过,则输出YES
		printf ("YES \n");
		}else{
		printf("No\n");
		}
	}
	return 0:
}

同样的,如果题目要求M个欲查询的数中每个数在N个数中出现的次数,那么可以把
hashtable数组替换为int型,然后在输入N个数时进行预处理,即当输入的数为x时,就令
hash Table[x]++,这样就可以用ON+M)的时间复杂度输出每个欲查询的数出现的次数。代码
如下:

Include <cstdio> 
const int maxn =100010;
 int hashtable[maxn]={0};
 int main(){
	int n, m, x;
	scanf("%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:
}

上面的两个问题都有一个特点,那就是直接把输入的数作为数组的下标来对这个数的性
质进行统计(这种做法非常实用,请务必掌握)。这是一个很好的用空间换时间的策略,因为
它将查询的复杂度降到了O(1)级别。但是,这个策略暂时还有一个问题一一上面的题目中出
现的每个数都不会超过10,因此直接作为数组下标是可行的,但是如果输入可能是10°大小
的整数(例如1111或者甚至是一个字符串(例如" Love You"),就不能将它们直接
作为数组下标了。要是有一种做法,可以把这些乱七八槽的元素转换为一个在能接受范围内
的整数,那该多么美好呀!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值