【PAT笔记】PAT中的散列思想

散列的介绍

散列(hash)是常用的算法思想之一,在很多程序上都会有意无意的使用到。用一句话来概括散列思想的话就是:“将元素通过一个函数转换为整数,使得该整数可以尽量唯一地代表这个元素”。其中把转换函数称为散列函数H。

那么对key是整数来说,有哪些常用的散列函数呢?一般来说,常见的散列函数有直接定址法、平方取中法、除留余数法,其中直接定址法是指恒等变换(即H(key)=key,很多问题都是直接把key作为数组下标,是最常见最实用的散列应用)。

散列的适用情形

那么,什么情况下使用散列思想呢?如何在竞赛或者考试中联想到散列思想呢?

  1. 在使用散列思想时,题目一般会给出两个字符串或者两个数组,这两个字符串或者的元素之间存在ans=S1-S2的类似关系;
  2. 题目用于其中某个字符串查询另一个字符串中的元素的情形;

散列的运用

下面给出一些散列思想的运用。

【PAT】B1039 

#include <stdio.h>
#include <string.h>
int main(){
	char hashTable[1010]={0};
	char str1[1010],str2[1010]; 
	int sum=0;
	gets(str1);
	gets(str2);
	int len_a=strlen(str1);
	int len_b=strlen(str2);
	for(int i=0;i<len_a;i++){  //数组的下标是珠子颜色的代表字符,统计每种颜色各有多少个珠子
		hashTable[str1[i]]++; 
	}
	for(int i=0;i<len_b;i++){  //统计完毕后,将需要得到的珠子减去原有的珠子,若出现负数,则表                            示某种颜色的珠子少于需求
		hashTable[str2[i]]--;
	}
	for(int i=0;i<len_b;i++){
		if(hashTable[str2[i]]<0){
			sum=sum+hashTable[str2[i]];
			hashTable[str2[i]]=0;
		}
	}

	if(sum<0) printf("No %d",0-sum);
	else printf("Yes %d",len_a-len_b);
	return 0;
} 

【PAT】B1042

#include <stdio.h>
#include <string.h>
int main(){
	int HashTable[256]={0};
	int k=0,len;
	char str[1010],j;
	gets(str);
	len=strlen(str);
	for(int i=0;i<len;i++){
		if(str[i]>='A'&&str[i]<='Z'){
			HashTable[str[i]-'A']++;  //将标记字符转化为唯一字符表示,这适用于字符串中给出大小写,但实际不需要区分大小写的情况
		}
		else if(str[i]>='a'&&str[i]<='z'){
			HashTable[str[i]-'a']++;
		}
		else 
			HashTable[str[i]]=0;
	}
	for(int i=0;i<26;i++){
		if(HashTable[i]>HashTable[k]){
			k=i;
		}
	}
	printf("%c %d\n",'a'+k,HashTable[k]);
	return 0;
}

【PAT】A1048

#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
	int n,m,a;
	int hashtable[1005]={0};
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%d",&a);
		++hashtable[a];  //将输入的数字作为数组的下标存储起来,把数组+下标的组合来存放该下标(即数字)的个数
	}
	for(int i=1;i<m;i++){
		if(hashtable[i]&&hashtable[m-i]){
			if(i==m-i&&hashtable[i]<=1){
				continue;
			}
			printf("%d %d\n",i,m-i);
			return 0;
		}
	}
	printf("No Solution\n");
	return 0;
} 

综    述

使用散列表示的方式一般有:

  1. 以数组的下标作为记录该数字的存在与否(通过int hashtable[maxn]={0}或者bool hashtable[maxn]={false});
  2. 以数组的下标作为改为字符记录;
  3. 以数组的下标和数组本身结合,记录下标(即数字或者字符)出现的次数(如hashtable[3]=2,hashtable['P']=3分别表示3出现了2次,字符P出现了3次)。

看到题目后应结合题目具体分析寻找最简单的解法。 

猜你喜欢

转载自blog.csdn.net/xt199711/article/details/86746507