Hash思想:映射

本文探讨了使用Hash思想解决ACM竞赛中数据范围有限并要求建立对应关系的题目,通过举例说明其在统计同成绩学生人数、排序问题、社交网络分析等题目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.使用Hash思想题目的特点


1、输入的数据的变化范围是有限的;

比如:

(1)、当读到N=0时输入结束。其中N不超过1000,成绩分数为(包含)0到100之间的一个整数。

(2)、每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且都处于区间[-500000,500000]的整数。

(3)、每个案例第一行两个整数N,M,2 <= N ,M<= 200。接下来有N行,第i(i = 1,2,…,N)行每一行有一个数,表示读者i-1最喜欢的图书的编号P(1<=P<=M)

2、能够得到对应关系

(1)、给定分数的人数。定义score[101],score[i]代表了成绩 i 的学生数;

(2)、给你n个整数,请按从大到小的顺序输出其中前m大的数。buf[1000000] 存放出现的数,出现为1,没出现为0.

(3)、。。。

2.题目(5个)


2.1本来不是Hash

但这个代码起始存在问题的。

/**
	输入一个数n,然后输入n个数值各不相同,再输入一个值x,
	输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1)。
*/

//----------------------------------------------------
//NB
//但是给的数超过20000就出错了!题目没说数的范围

#include<stdio.h>
#include<memory.h>

void main(){
        int n,i,temp,a[20000];
        while(~scanf("%d",&n)){
                memset(a,-1,sizeof(a));
                for(i=0;i<n; a[temp]=i++) //大神的Hash思想
                      scanf("%d",&temp);
                     
               scanf("%d",&temp);
               printf("%d\n",a[temp]);
        }        
}

2.2 题目1018:统计同成绩学生人数

http://ac.jobdu.com/problem.php?pid=1018
 
 #include <stdio.h>
 
 int main(){
	int n;
	while (scanf ("%d", &n) != EOF && n != 0){
		int Hash[101]= {0};
		
		for (int i =1; i <= n; i++){
			int x;
			scanf("%d", &x);
			Hash[x] ++;
		}
		int x;
		scanf("%d", &x);
		printf("%d\n", Hash[x]);
	}
	return 0;
 }
 
 
 
 #include <stdio.h>

int buf[101]={0}; //存放该成绩的人数,满分 100
/*-----------------------------------------------------
  WA:buf声明为全局变量。对于多组数据,在统计下一组数据
  时并没有把之前的数据清空,所以出现错误 。
  
  声明为全局变量应该考虑多组数据时是否会变?如果变可以
  在下次使用前清空,或者声明为局部变量。一般小数据没有
  必要什么为全局。

-----------------------------------------------------*/
int main(){

	int n; // n <= 1000
	while (scanf ("%d", &n) != EOF && n){
		for (int i =0; i < 101; i++){
			buf[i] = 0;
		}//清空
		
		for (int i = 0; i < n; i++){
			int score;
			scanf ("%d", &score);
			buf[score]++; // 记录该成绩人数
		} // Hash思想

		int dscore;
		scanf ("%d", &dscore); //给定成绩
		printf("%d\n", buf[dscore]);
	}
	return 0;
}



2.3 题目1431:Sort

http://ac.jobdu.com/problem.php?pid=1431
Runtime Error:
1.地址越界:数字大小定义为100,初始化是1000.


#include <stdio.h>
#define OFFSET 500000
int Hash[1000001];	//数据量大,使用全局,下次使用清空
int main(){
	#ifdef ONLINE_JUDGE
	#else
	freopen("E:\\in.txt", "r", stdin);
	#endif
	
	
	int n, m;
	while (scanf ("%d %d", &n, &m) != EOF){
		for (int i = -500000; i <= 500000; i++){
			Hash[i+OFFSET] = 0;
		} // 多次测试,清空:0代表未,1出现
	
		for (int i = 0; i < n; i++){
			int x;
			scanf("%d", &x);
			Hash[x+OFFSET] = 1;
		} // 标记出现的数
		
		for (int i = 500000; i >= -500000; i--){
			if (Hash[i+OFFSET] == 1){
				printf("%d", i);
				m --;
				if (m != 0){
					printf(" ");
				}
				else{
					printf("\n");
					break;
				}//if-else
			}// if
		}// for
	}// while:多组
	
	return 0;
}



2.4 题目1156:谁是你的潜在朋友

http://ac.jobdu.com/problem.php?pid=1156
Runtime Error:
数组没加取址符&:scanf("%d", stu[i]); 

/**
 * int n(people), m(book);
 * the same book
 * 每个人有几个潜在的朋友
 
4  5    //4个人,5本书
2       //1 喜欢 2号书
3
2
1
 
*/
 
 
#include <stdio.h>
 
int main(){
    #ifdef ONLINE_JUDGE
    #else
    freopen("E:\\in.txt", "r", stdin);
    #endif
     
    int n,m;
     
    while (scanf("%d%d", &n, &m) != EOF){
        int stu[210]; //book id
        int book[210]; // num of stu
         
        for (int i = 1; i <= m; i++){
            book[i] = 0;
        }// 借书人初为0
         
        for (int i = 1; i <= n; i++){
            scanf("%d", &stu[i]); // WA:没加取址符
            book[stu[i]]++;//人数+1
        }// 读者i喜欢的书号
         
        for (int i = 1; i <= n; i++){
            if( book[stu[i]] == 1)
                printf("BeiJu\n");//只有自己喜欢
            else
                printf("%d\n", book[stu[i]] - 1);//去掉自己,就是其他人的数量
         
        }// print
     
     
    }// while: zu
 
    return 0;
}



2.5 题目1088:剩下的树

http://ac.jobdu.com/problem.php?pid=1088

/**
 * Hash思想:有限的取值范围:输入有限的数据,使用的
 * 空间有限,可以建立下标对应关系。
 *
 * int L[10001];共10001个位置
 * 有树为1,无为0
 * 每输入一个区间[a,b],把【L[a],L[b]】标记为0
 * 最后遍历统计1的个数。
 */

 #include <stdio.h>
 
 #define MAXLEN 10001
 int main(){
 #ifdef ONLINE_JUDGE
 #else
 freopen("E:\\in.txt", "r", stdin);
 #endif

	int L[MAXLEN];
	int l, m;
	while (scanf ("%d%d", &l, &m) != EOF){
		for (int i = 0; i <= l; i++){ //注意i的范围是i<=l not i<l
			L[i] = 1;
		}// 初始化,种l+1棵树
		
		int a, b;
		for (int i = 1; i <= m; i++){
			scanf("%d%d", &a, &b);
			for(int j = a; j <= b; j++){
				L[j] = 0;
			}// 移走
		}// m组
		
		int left=0;
		for (int i = 0; i <= l; i++){
			if (L[i] == 1)
				left++;
		}
		printf("%d\n", left);
	}// while:zu
	return 0;
 }






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值