分组统计 C/C++实现

本文详细解析了一种分组统计算法,通过输入一组数字和其对应的分组,统计每个分组内数字的出现频率,并按分组输出。算法首先对数字进行排序和去重,然后建立映射关系,统计各分组下数字的出现次数。

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

题目描述

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

输入描述:

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

输出描述:

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

示例1

输入

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}

 

解题思路:

我们会先得到一组数字num[n]。我们是按照出现过的数字从小到大排序且不重复的条件下完成输出的。

因此,我们可以令开辟一个put数组和num数组存储相同的内容。

然后排序,去重,每个分组的输出列表。即题设的2 3 8。

之后,我们会得到每个数字对应的分组序号。

在这里我们可以注意一个点就是,我们每组的输出只和我们的输出列表(put)有关,因此,我们只需要记录输出列表每个数字出现的次数即可。(用put输出记录的数值,再用一个同样大小的数组记录对应数值在每组中出现的次数)

因此,我们利用了一个结构体数组pos。里面有一个flag表示是否要求我们输出这个分组。还有一个val数组,用于和我们的put数组对应,记录该数值在本组中出现的次数。

举例来说:

我们的输出列表put是2 3 8

put        0  1  2

内容      2  3  8

每组pos[i]的输出列表也是2 3 8

pos[i]val     0 1 2

内容           0 0 0

当我们输入了一个分组1(它对应的值是3)

我们就可以把第一个分组的flag设为1,表示它在后面需要输出

然后找到3在put输出列表中的位置(此处put[1]==3)

我们就可以在val数组中同样的位置计数,这时我们的pos[1]val数组就变成了

pos[1]val   0 1 2 (注意,这里的0 1 2与put数组的0 1 2是对应的,put表示数值,val表示数值出现的次数)

内容          0 1 0     (val数组的1对应put数组里的3,计数器+1)

重复处理所有的分组:

            for(int i=0;i<n;i++){
                int temp;
                cin>>temp;//输入分组序号
                pos[temp].flag=1;//该分组需要输出flag设为1
                for(int j=0;j<len;j++){//找到对应分组下的输入数字(如3组对应的1)
                    if(num[i]==put[j]){//找到这个数字在输出列表中的位置(找到数字1在put数组中存储的位置)
                    pos[temp].val[j]++;(对应数值计数器加1)
                    break;
                    }
                }
            }

最后我们得到的结果(以第一组为例)

pos[1]val   0 1 2       put数组的0 1 2是对应的即2 3 8

内容          0 2 1       2 3 8出现的次数                0 2 1

最后进行简单的输出处理就可以了,先输出前n-1个分组,最后输出最后一个分组就可以解决{}匹配和逗号的问题

最后是AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct position{
	int flag;
	int val[150];
}pos[150];

int main()
{
	int m;
	int num[100],put[100];
	while(cin>>m){
		while(m--){
			for(int i=0;i<150;i++){//每组数据都要初始化
				memset(pos[i].val,0,sizeof(pos[i].val));
				pos[i].flag=0;
			}
			int n;
			cin>>n;
			for(int i=0;i<n;i++){输入数据并得到put数组
				cin>>num[i];
				put[i]=num[i];
			}
			sort(put,put+n);
			int len=0;
			for(int i=1;i<n;i++){
				if(put[len]==put[i]) continue;
				else put[++len]=put[i];
			}//得到递增不重复的输出列表
			++len;//由于len初值是0,但已经表示了put[0],所以len再自增一次才是put数组的长度
			for(int i=0;i<n;i++){//对每组的输出列表计数
				int temp;
				cin>>temp;
				pos[temp].flag=1;
				for(int j=0;j<len;j++){
					if(num[i]==put[j]){
					pos[temp].val[j]++;
					break;
					}
				}
			}
			for(int i=0;i<150;i++){//输出结果
				if(pos[i].flag!=0){
					printf("%d={",i);
					for(int j=0;j<len-1;j++){
						printf("%d=%d,",put[j],pos[i].val[j]);
					}
					printf("%d=%d}\n",put[len-1],pos[i].val[len-1]);
				}
			}
			
		}
	}
		
	return 0;
}

             

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值