《算法笔记》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}
题意
将第一行数字按照第二行的编号进行分组,记录第一个行数字中不同数字出现的次数
思路
- 1.哈希,将数字和编号作为下标来统计出现次数
- 2.二维数组或者结构体皆可
- 3.将第一行和第二行分别用数组存下来后,一起遍历存储
坑点
- 1.数据范围,数字和编号不小于100,大概开1000足矣
- 2.由于是多组输入输出,需要复原数组或者结构体为初始值
- 3.下标大小
代码
#include<bits/stdc++.h>
using namespace std;
//组别里的数都出现了多少字
struct name{
int num[1100];
int id=0; //记录组别的状态
};//组别
int main()
{
int m;
scanf("%d",&m);
while(m--)
{
int a[1100]={0};//数字
int b[105]={0};//组别
int c[1100]={0};
int ans[105]={0};//去重后的数字
int cnt=0;//不同的数有多少个
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x=0;
scanf("%d",&x);
c[i]=x;
a[x]++;//记录第一行数字下标为x时出现的次数
}
for(int i=0;i<1100;i++)
{
if(a[i]>0)
{
ans[cnt]=i;//出现过的数字赋值给ans数组
cnt++;//记录不同数字的个数 且从小到大
}
}
int maxn=-1000000;
for(int i=0;i<n;i++)
{
scanf("%d",&b[i]);//组别
maxn=max(maxn,b[i]);//更新最大组别的数字
}
name zubie[maxn+1]={};//有效的控制了结构体数组的大小
for(int i=0;i<n;i++)
{
//bi是组别编号数组
//ci是数字的数组
zubie[b[i]].num[c[i]]++;
zubie[b[i]].id++;
}
for(int i=0;i<maxn+1;i++)
{
if(zubie[i].id>=1)//判断组别是否存在
{
printf("%d={",i);
for(int j=0;j<cnt;j++)
{
printf("%d=%d",ans[j],zubie[i].num[ans[j]]);//输出去重后的数字和出现的次数
if(j!=cnt-1)
{
printf(",");
}
}
printf("}\n");
}
}
}
return 0;
}
总结
双重哈希,数字和编号均需要哈希,题目数据比较坑,细心分析即可。