算法笔记练习 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 语言思路
变量说明:
inputs
结构数组:长度为 n,接收所有输入,每个元素包括该数字的值以及它所属的组num_cnt
,grp_cnt
分别统计总共有多少种不同的数字,有多少种不同的组diffrentNum
数组:长度为 n,前num_cnt
个元素有效,存放所有不同数字的值diffrentGrp
数组:长度为 n,前grp_cnt
个元素有效,存放所有不同组的组名answer
二维数组(grp_cnt
行,num_cnt
列):第 i 行 j 列的值表示diffrentGrp
第 i 个组中diffrentNum
第 j 个数的出现次数
步骤:
- 用
inputs
接收所有数据,并生成num_cnt
,grp_cnt
,diffrentNum
,diffrentGrp
- 对
diffrentNum
,diffrentGrp
分别从小到大进行排序 - 遍历
inputs
,根据inputs
,diffrentNum
,diffrentGrp
来生成answer
- 输出
answer
C 语言代码
#include <stdio.h>
#include <stdlib.h>
// 用来存放输入的数据
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++ 思路
变量说明:
setNum
,setGrp
分别是 C 语言代码里diffrentGrp
,diffrentNum
的 set 版本inputs
,answer
与 C 语言代码中的含义相同
思路参考 C 语言思路
C++ 代码
#include <cstdio>
#include <set>
#include <vector>
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;
}