算法笔记练习 4.2 散列 问题 B: 分组统计

算法笔记练习 题解合集

题目链接

题目

题目描述
先输入一组数,然后输入其分组,按照分组统计出现次数并输出,参见样例。

输入
输入第一行表示样例数m,对于每个样例,第一行为数的个数n,接下来两行分别有n个数,第一行有n个数,第二行的n个数分别对应上一行每个数的分组,n不超过100。

输出
输出m行,格式参见样例,按从小到大排。

样例输入
1
7
3 2 3 8 8 2 3
1 2 3 2 1 3 1

样例输出
1={2=0,3=2,8=1}
2={2=1,3=0,8=1}
3={2=1,3=1,8=0}

题解

一直习惯用 C 语言刷题,几乎没写过 C++,所以第一次AC用的是 C 语言,手动实现了类似于 C++ 里面 set 的功能,虽然AC了但是觉得十分麻烦…

于是花了一天补习了一下 C++ 的 STL,用同样的思路重写了一版,下面是两个版本

C 语言思路

变量说明:

  1. inputs结构数组:长度为 n,接收所有输入,每个元素包括该数字的值以及它所属的组
  2. num_cntgrp_cnt分别统计总共有多少种不同的数字,有多少种不同的组
  3. diffrentNum数组:长度为 n,前num_cnt个元素有效,存放所有不同数字的值
  4. diffrentGrp数组:长度为 n,前grp_cnt个元素有效,存放所有不同组的组名
  5. answer二维数组(grp_cnt行,num_cnt列):第 i 行 j 列的值表示diffrentGrp第 i 个组中diffrentNum第 j 个数的出现次数

步骤:

  1. inputs接收所有数据,并生成num_cntgrp_cntdiffrentNumdiffrentGrp
  2. diffrentNumdiffrentGrp分别从小到大进行排序
  3. 遍历inputs,根据inputsdiffrentNumdiffrentGrp来生成answer
  4. 输出answer

C 语言代码

#include 
#include  
// 用来存放输入的数据 
typedef struct{
	int value;	// 数字的值 
	int groupNo;// 所属组号 
} Input;
// qsort 排序函数 
int cmpInt(const void *ca, const void *cb);
int main(){
	int m, n, num_cnt, grp_cnt, i, j, k;
	while (scanf("%d", &m) != EOF){
		while (m--){
			num_cnt = 1;	// num_cnt 统计有几种不同的数字
			grp_cnt = 1; 	// grp_cnt 统计有几种不同的组名 
			scanf("%d", &n);
			Input inputs[n];		// 存放所有输入的数据 
			int diffrentNum[n];		// 记录所有出现过的不同数字的值 
			int diffrentGrp[n];		// 记录所有出现过的不同分组的组名 
			// 读入数字的值,并生成 diffrentNum,num_cnt
			scanf("%d", &inputs[0].value);
			diffrentNum[0] = inputs[0].value;
			for (i = 1 ; i < n; ++i){
				scanf("%d", &inputs[i].value);
				// 在 diffrentNum 数组中找输入的数字,如果没有则在后面插入 
				for (j = 0 ; j < num_cnt; ++j)
					if (diffrentNum[j] == inputs[i].value)
						break;
				if (j == num_cnt)
					diffrentNum[num_cnt++] = inputs[i].value;
			}
			// 读入分组的值,并生成 diffrentGrp,grp_cnt
			scanf("%d", &inputs[0].groupNo);
			diffrentGrp[0] = inputs[0].groupNo;
			for (i = 1 ; i < n; ++i){
				scanf("%d", &inputs[i].groupNo);
				// 在 diffrentGrp 数组中找输入的数字,如果没有则在后面插入 
				for (j = 0 ; j < grp_cnt; ++j)
					if (diffrentGrp[j] == inputs[i].groupNo)
						break;
				if (j == grp_cnt)
					diffrentGrp[grp_cnt++] = inputs[i].groupNo;
			}
			// 分别对 diffrentNum,diffrentGrp 按从小到大排序 
			qsort(diffrentNum, num_cnt, sizeof(int), cmpInt); 
			qsort(diffrentGrp, grp_cnt, sizeof(int), cmpInt);
			// answer[i][j] 表示第 i 组中,第 j 个数字出现的次数 
			// answer 中组和数字的值按顺序对应 diffrentGrp,diffrentNum
			int answer[grp_cnt][num_cnt];
			for (i = 0; i < grp_cnt; ++i)
				for (j = 0; j < num_cnt; ++j)
					answer[i][j] = 0;
			// 遍历 inputs 数组,生成 answer 
			for (i = 0; i < n; ++i){
				for (j = 0; j < grp_cnt; ++j){
					if (diffrentGrp[j] != inputs[i].groupNo)
						continue;
					for (k = 0; k < num_cnt; ++k){
						if (diffrentNum[k] != inputs[i].value)
							continue;
						++answer[j][k];
						break;
					}
					break;
				} 
			}
			// 输出 answer 
			for (i = 0; i < grp_cnt; ++i){
				printf("%d={", diffrentGrp[i]); 
				int flag = 0;
				for (j = 0; j < num_cnt; ++j){
					if (flag)
						putchar(',');
					flag = 1;
					printf("%d=%d", diffrentNum[j], answer[i][j]); 
				}
				printf("}\n"); 
			} 
		} 
	}
	return 0;
} 

int cmpInt(const void *ca, const void *cb){
	int ret = 0;
	int a = *(int*)ca;
	int b = *(int*)cb;
	if (a > b) ret = 1;
	else if (a < b) ret = -1; 
	return ret;
} 

C++ 思路

变量说明:

  1. setNumsetGrp分别是 C 语言代码里diffrentGrpdiffrentNum的 set 版本
  2. inputsanswer与 C 语言代码中的含义相同

思路参考 C 语言思路

C++ 代码

#include 
#include 
#include 
using namespace std;
typedef struct{	// 用来存放输入的数据 
	int value;	// 数字的值 
	int groupNo;// 所属组号 
} Input;
int main(){
	int m, n;
	while (scanf("%d", &m) != EOF){
		while (m--){
			scanf("%d", &n);
			Input inputs[n];
			set<int> setNum;
			set<int> setGrp;
			// 用 inputs 接收所有数据,顺便生成 setNum,setGrp
			for (int i = 0; i != n; ++i){
				scanf("%d", &inputs[i].value);
				setNum.insert(inputs[i].value);
			} 
			for (int i = 0; i != n; ++i){
				scanf("%d", &inputs[i].groupNo);
				setGrp.insert(inputs[i].groupNo);
			}
			int sizeGrp = setGrp.size();
			int sizeNum = setNum.size();
			// 把两个 set 都转为 vector 便于统计结果 
			vector<int> vecGrp;
			vector<int> vecNum;
			for (int i = 0; i != sizeGrp; ++i){
				vecGrp.push_back(*setGrp.begin());
				setGrp.erase(*setGrp.begin());
			}
			for (int i = 0; i != sizeNum; ++i){
				vecNum.push_back(*setNum.begin());
				setNum.erase(*setNum.begin());
			}
			// answer 放答案 
			int answer[sizeGrp][sizeNum];
			for (int i = 0; i != sizeGrp; ++i)
				for (int j = 0; j != sizeNum; ++j)
					answer[i][j] = 0;
			// 统计每个数在每个组的出现次数 
			for (int i = 0; i != n; ++i){
				for (int j = 0; j != sizeGrp; ++j){
					if (vecGrp[j] != inputs[i].groupNo) continue;
					for (int k = 0; k != sizeNum; ++k){
						if (vecNum[k] != inputs[i].value) continue;
						++answer[j][k];
						break;
					}
					break;
				}
			}
			// 输出 answer
			for (int i = 0; i != sizeGrp; ++i){
				printf("%d={", vecGrp[i]); 
				int flag = 0;
				for (int j = 0; j != sizeNum; ++j){
					if (flag)
						putchar(',');
					flag = 1;
					printf("%d=%d", vecNum[j], answer[i][j]); 
				}
				printf("}\n"); 
			}
		} 
	} 
	return 0;
} 

你可能感兴趣的:(算法笔记)