一文帮你弄懂散列是什么

什么是散列?

我们先看这样一个问题:给出N个正整数,再给出M个正整数,问你M中出现的每个数是否在N中出现过。其中N,M<=10³。

最直观的思路就是暴力枚举,先在M中挑一个数,然后和N中的数一一比较,比较完了之后再在M中挑第二个数,以此类推。但是这样的复杂度达到了O(MN),是不优秀的算法。

不妨用空间换时间,让M个整数做为数组的下标建立数组。比如M个数分别为5,9,12,7,N个数分别为9,7,12,6。那么先建立bool数组hashtable[Maxn]={false},然后遍历9,7,12,6这几个下标对应的值由false改为true,然后再去遍历5,9,12,7,但是遍历的同时加一句hashtable[x]是否为true,来判断是否出现过。

bool hashtable[10000]={false};
int mian(){
	int n,m,x;
	scanf{"%d%d",&n,&m};
	for(int i=0;i<n;i++){
		scanf("%d",&x);
		hashtable[x]=true;  //数字x出现过
	}
	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型,每次出现了则++。(自己动手试一试)

以上题目都是直接把输入的数作为数组的下标来进行统计(非常实用!),假如我们要统计一篇英文文章中love字符串出现的次数该怎么办呢?那我们就用love做下标来统计咯。但是一般来说只有整数才可以做下标,怎么办?于是我们就要用到散列的思想。

散列官方含义是“将元素通过一个函数转化为整数,使得该整数可以尽量唯一地代表这个元素。”

通俗点就是,将元素化为一个唯一能表示它的整数,以后见到这个整数就相当于见到见到了该元素,那么我拿这个整数做下标实际上就是拿这个字符做下标,根据这个思想,岂不是万物皆可做下标。

常用的方法有:除留余数法、线性探查法、平方探查法、链地址法等,这些方法不再此处细讲,因为接下来要讲的可以省去这一步。

C++中有个map库,就可以让字符直接做下标,电脑已经帮我们对这些字符进行了哈希处理(也就是散列处理,因为散列的英文是hash),我们接下来看到题来实践一下。

题目: 到底买不买
问题描述:小红想买些珠子做一串自己喜欢的珠串。卖珠子的摊主有很多串五颜六色的珠子,但不肯把任何一串拆开卖。于是小红请你帮忙判断,某串珠子是否包含了全部自己想要的珠子?如果是,告诉她有多少多余的珠子,如果不是,告诉她缺少了多少珠子。
分析:这里用09,az,A~Z范围内的字符表示颜色。
输入格式:每个测试用例分别再两行中先给出摊主珠子和小红想买做的珠串,两串都不超过1000个珠子。
输出格式:如果可以买,则输出YES以及有多少个多余的珠子;如果不可以,则在一行中输出NO以及缺了多少珠子。期间用一个空格分隔。
输入用例:
ppRYYGrrYBR2258
YrR8RrY
输出样例:
YES 8

思路分析:将老板的珠子放入哈希表中,以珠子颜色为键,珠子数量为值,形成键值对,然后拿小红所需要的珠子颜色为键去访问老板的珠子哈希表,如果有,则老板珠子哈希表对应的值就减一,没有,缺的珠子就加一,最后,如果缺的珠子大于0,说明不可以买,并输出缺的珠子,如果缺的珠子等于0(即没缺珠子),那么这个时候老板的珍珠数量减去小红的珍珠数量就是多余的珍珠数量。

#include<iostream>
#include<map>
using namespace std;

int main() {
	int lack=0,surplus=0;
	string boss;
	string hong;
	cin >> boss;
	cin >> hong;
	map<char, int> pearl;//哈希表没有键值对的地方就是0-0
	for (int i = 0; i < boss.length(); i++) {
		pearl[boss[i]]++;
	}
	for (int i = 0; i < hong.length(); i++) {
		if (pearl[hong[i]] == 0)
			lack++;
		else
			pearl[hong[i]]--;//相当于把珠子给了小红,然后摊主的珠子减一,防止后面小红要好多颗珍珠,摊主就只有一颗珍珠在这里唬人
	}
	surplus = boss.length() - hong.length();
	if (lack > 0)
		cout << "NO!!" << "  " << lack << endl;
	else
		cout << "YES!!" << "  "<< surplus  <<endl;
	return 0;
}

相信看到这你已经弄懂了什么是散列,并且知道怎么去运用了,一定要多动手实践一下。

猜你喜欢

转载自blog.csdn.net/Dai_sir_man/article/details/120182871