问题 B: 分组统计

分组统计

问题 B: 分组统计时间限制: 1 Sec 内存限制: 32 MB

提交: 416 解决: 107

[提交][状态][讨论版][命题人:外部导入]

题目描述

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

输入

输入第一行表示样例数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}

思考

http://codeup.cn/problem.php?cid=100000582&pid=1

这个是典型的哈希算法了。

这个样例是统计每组数字里面各数字(出现在第一行的数字,这一次是3,2,8)的个数。

所以每一组数字要个数组3,记录2,3,8的个数

先搞一个在n个数字第一次出现时的数组num,记录那些数字出现了,出现了几次,以该数字为下标的数组值++,那这个数组大小应该是很大的啊 。

再来就是分组了,再来一个数组zu,以上一行出现过数字为下标,值为所分的组。

n不超过100。怎么表示这种性质呢?结构体?一个整型,记录其在第一行的n个数里的出现次数,再来一个数组,记录自己在不同组的出现次数。

组数肯定要小于n

本地实现

这问题几个月之前就遇到过了。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//#include <limits.h>
#define maxn 10005
int cmp(const void*a, const void*b){
    return *(int*)a - *(int*)b;//升序
}
int main(){
    int m;
    while(scanf("%d", &m) != EOF){
        while(m--){
            int n;
            scanf("%d", &n);
            int cishu[maxn][n+1]= {0};
            //int temp[n+1] = INT_MAX;
            int temp[n+1] = {0};
            for(int i = 1; i <= n; i++){
                scanf("%d", &temp[i]);
                cishu[temp[i]][0]++;//将第一行数读入数组temp,并且在相应行第0列记录出现在第一行出现次数
            }
            int zu[n+1] = {0}, num = 0, kzu[n+1] = {0};
            for(int i = 1; i <= n; i++) {
                scanf("%d",&zu[i]);
                kzu[zu[i]]++;
                cishu[temp[i]][zu[i]]++;
            }
            /*二维数组里行代表这个数,列代表该行对应数在某组里出现的次数*/
            for(int i = 1; i <= n; i++) {
                if(kzu[i] > 0)
                    num++;
            }
            //num记录分的组的个数
            /*该对第一行的n个数按大小排序了*/
            qsort(temp+1, n, sizeof(temp[0]), cmp);
            /*for(int i = 1; i <= n; i++){
                printf("%d\n", temp[i]);
            }//排序正确*/
            /*剔除重复项,建立新数组*/
            int newtemp[n+1], newxu = 2;
            newtemp[1] = temp[1];
            for(int i = 2; i <= n; i++) {
                if(temp[i] != temp[i-1])//if语句的括号后面跟分号,编译器竟然没error
                    newtemp[newxu++] = temp[i];
            }
            /*for(int i = 1; i < newxu; i++){
                printf("%d\n", newtemp[i]);
            }//剔除重复项,新数组正确*/
            for(int j = 1; j <= num; j++) {
                printf("%d={", j); //第j组
                for(int i = 1; i < newxu; i++){
                        printf("%d=%d", newtemp[i], cishu[newtemp[i]][j]);
                        if(i < newxu-1)
                            printf(",");
                }
                printf("}\n");
            }
        }
    }
    return 0;
}

别人的代码1-二维数组

s066 Problem B 分组统计 - CSDN博客 https://blog.csdn.net/fantasydreams/article/details/79114487

#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
const int MaxN = 102;
int main()
{
#ifdef _DEBUG
    ifstream cin("data.txt");
#endif // _DEBUG
    //利用链表散列进行统计,这里用二维数组模拟
    int m, n;
    while (cin >> m)
    {
        while (m--)
        {
            int Table[MaxN][MaxN] = {0}, classFlag[MaxN] = {false}, Class[MaxN], ClaN = 0, Num[MaxN], tmp, NumUi[MaxN], N = 0;
            cin >> n;
            for (int i = 0; i < n; ++i)
                cin >> Num[i];//读入第一行所有数
            for (int i = 0; i < n; ++i)
            {
                cin >> tmp;
                if (!classFlag[tmp])
                {
                    classFlag[tmp] = true;
                    Class[ClaN++] = tmp;//该组的序号第一次出现时,记录进来
                }
                Table[tmp][Table[tmp][MaxN - 1]++] = Num[i];//建立这个表,第几组就是第几行 ,避免了数组越界
            }//该数是第几组存进第几行的,存进哪一列呢?从第1列,开始存,该行最后一列记录了该组的数字个数
            sort(Class, Class + ClaN);//组序号排序 ,ClaN记录组的个数
            sort(Num, Num + n);//第一行数字排序
            /*剔除重复项,建立新数组*/
            for (int i = 0; i < n; ++i)
            {
                if (N == 0 || Num[i] != NumUi[N-1])
                {
                    NumUi[N++] = Num[i];
                }
            }

            for (int k = 0; k < ClaN; ++k)
            {
                printf("%d={", Class[k]);/*组号*/
                for (int h = 0; h < N; ++h)/*按第一行数字顺序*/
                {   /*查询,如果出现相同的,则数字加1*/
                    int c = 0, j = 0;
                    for (; j < Table[Class[k]][MaxN - 1]; ++j)
                    {
                        if (Table[Class[k]][j] == NumUi[h])
                            ++c;
                    }
                    printf("%d=%d", NumUi[h], c);
                    if (h < N-1)
                        printf(",");
                }
                printf("}\n");
            }
        }
    }

#ifdef _DEBUG
    cin.close();
    system("pause");
#endif // _DEBUG

    return 0;
}

别人的代码2-散列

C/C++[codeup 2066]分组统计 - CSDN博客 https://blog.csdn.net/u014281392/article/details/80841162

C++ STL算法系列4---unique , unique_copy函数 - 夏雪冬日 - 博客园 https://www.cnblogs.com/heyonggang/archive/2013/08/07/3243477.html

#include <iostream>
#include <algorithm>     //max_element,unique_copy
#include <cstring>
#include <vector>
using namespace std;
int main() {
    int M;
    while(cin>>M) {
        while (M--) {
            int N;                  //输入数据的个数
            cin >> N;
            int nums[N], cls[N];    //数据和类别
            for (int i = 0; i < N; i++)
                cin >> nums[i];
            for (int i = 0; i < N; i++)
                cin >> cls[i];
            // 数据的最大值和类别
            int max_cls = *max_element(cls, cls + N);
            int max_num = *max_element(nums, nums + N);
            // hash二维数组计数
            int hashTable[max_cls + 1][max_num + 1];
            // 全0初始化
            memset(hashTable, 0, sizeof(hashTable));
            for (int i = 0; i < N; i++)
                hashTable[cls[i]][nums[i]]++;
            //类排序去重
            vector<int> v2;
            sort(cls, cls+N);
            unique_copy(cls, cls + N, back_inserter(v2));
            //nums排序去重
            vector<int> v;
            sort(nums, nums + N);
            unique_copy(nums, nums + N, back_inserter(v));
            for (int i = 0; i < v2.size(); i++) {
                cout << v2[i] << "={";
                for (int j = 0; j < v.size(); j++) {
                    cout << v[j] << ‘=‘ << hashTable[v2[i]][v[j]];
                    if (j < v.size() - 1) cout << ‘,‘;
                }
                cout << ‘}‘ << endl;
            }
        }
    }
    return 0;
}

这里比较重要的是,取得容器内最大值,防止二维数组越界问题。

防止越界的散列

C++ STL之min_element()与max_element()(取容器中的最大最小值) - Angel_Kitty - 博客园 https://www.cnblogs.com/ECJTUACM-873284962/p/6734225.html

#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
      return a<b;
      // return a>b;
}
int main()
{
      int num[]={2,3,1,6,4,5};
      cout<<"最小值是 "<<*min_element(num,num+6)<<endl; //默认升序
      cout<<"最大值是 "<<*max_element(num,num+6)<<endl;
      cout<<"最小值是 "<<*min_element(num,num+6,cmp)<<endl; //可以修改为  return a>b;改降序
      cout<<"最大值是 "<<*max_element(num,num+6,cmp)<<endl;
      return 0;
}

关于c语言初始化的问题

C/C++数组初始化的一些误区 - CSDN博客 https://blog.csdn.net/u014417133/article/details/77185009

也就是说,要置零,使用memset最好了。

memset(cur,0,sizeof(cur))

AC代码

#include <iostream>
#include <algorithm>     //max_element,unique_copy
#include <cstring>
#include <vector>
using namespace std;
int main() {
    int M;
    while(cin>>M) {
        while (M--) {
            int N;                  //输入数据的个数
            cin >> N;
            int nums[N], cls[N];    //数据和类别
            for (int i = 0; i < N; i++)
                cin >> nums[i];
            for (int i = 0; i < N; i++)
                cin >> cls[i];
            // 数据的最大值和类别
            int max_cls = *max_element(cls, cls + N);
            int max_num = *max_element(nums, nums + N);
            // hash二维数组计数
            int hashTable[max_cls + 1][max_num + 1];
            // 全0初始化
            memset(hashTable, 0, sizeof(hashTable));
            for (int i = 0; i < N; i++)
                hashTable[cls[i]][nums[i]]++;
            //类排序去重
            vector<int> v2;
            sort(cls, cls+N);
            unique_copy(cls, cls + N, back_inserter(v2));
            //nums排序去重
            vector<int> v;
            sort(nums, nums + N);
            unique_copy(nums, nums + N, back_inserter(v));
            for (int i = 0; i < v2.size(); i++) {
                cout << v2[i] << "={";
                for (int j = 0; j < v.size(); j++) {
                    cout << v[j] << ‘=‘ << hashTable[v2[i]][v[j]];
                    if (j < v.size() - 1) cout << ‘,‘;
                }
                cout << ‘}‘ << endl;
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lingr7/p/9536396.html

时间: 2024-08-03 00:48:23

问题 B: 分组统计的相关文章

分组统计:count,group by,having, order by

--统计男女生的总人数select COUNT(*) from Student where Sex='男'select COUNT(*) from Student where Sex='女'--统计每一个班级的总人数select COUNT(*) from Student where ClassId=1--分组统计:需要按班级分组,每一个组得到一个统计结果--select 字段列表 from 表列表 where 数据源筛选 group by 分组字段列表 order by 排序字段列表selec

分组统计查询(学习笔记)

查询出公司每个月支出的工资总和 --查询出公司每个月支出的工资总和 SELECT SUM(sal) FROM emp; 查询出公司的最高工资,最低工资和平均工资 --查询出公司的最高工资,最低工资和平均工资 SELECT MAX(sal),MIN(sal),ROUND(AVG(sal),2) FROM emp; 统计出公司最早雇佣和最晚雇佣的雇佣日期 --统计出公司最早雇佣和最晚雇佣的雇佣日期 SELECT MIN(hiredate) 最早雇佣日期 , MAX(hiredate) 最晚雇佣日期

010.简单查询、分组统计查询、多表连接查询(sql实例)

-------------------------------------day3------------ --添加多行数据:------INSERT [INTO] 表名 [(列的列表)] --SELECT UNION --SELECT 'HAHA',1,32--UNION ALL --全部显示/显示重复数据 即使集合相同--UNION---------将查询的两个结果集合并.结构必须一致 -->常见面试题 --SELECT 'HEHE',2,33------将查询结果添加到列表中(子查询)IN

003.分组统计查询和表连接查询

--分组统计查询 group by having 1 select 分组字段 ,聚合函数 2 having 后常跟聚合函数,也可以跟分组字段 3 where 后不可以直接跟聚合函数 4 where(筛选行) -group by (分组) -having (筛选组) --表连接查询 1 笛卡尔积 (交叉连接 cross join) a*b A) SELECT * FROM A,B B) SELECT * FROM A CROSS JOIN B 2 内连接 原理: 将两个表中关联字段相等的行查询出来

Excel 中使用SQL 语句查询数据(八)-----用Group by 进行分组统计

今天要和大家分享用在sql 语句中使用group by来进行分组统计.大家首先来看一下数据源. 用OLE DB 打开数据源,(步骤请参考本系列第一篇博文) 最后一条语句group by Item ,就是以Item 列分组. 结果如下 按照item 分类汇总

组函数及分组统计

分组函数 SQL中常用的分组函数 Count(): 计数 Max():求最大值 Min():求最小值 Avg():求平均值 Sum():求和 -- 统计emp表中的人数 select count(*) from emp; -- 统计获得奖金的人数 select count(comm) from emp; -- 求所有雇员的最低工资 select min(sal) from emp; -- 求所有雇员的最高工资 select max(sal) from emp; -- 求部门编号为20的雇员的平均

6.数据分组-统计信息

---数据分组-统计信息----- --select 字段列表from 表列表 where 对数据源进行数据筛选group by 分组字段列表Order by 排序字段列表 --1.得到所有学员总人数 select COUNT(*) from Student --2.得到男女生的人数 select COUNT(*) from Student where Sex='男' select COUNT(*) from Student where Sex='女' --使用分组统计 select COUNT

《卸甲笔记》-分组统计查询

统计函数对比 1查询出公司每个月支出的月工资总和 Oracle SQL> select SUM(sal) from emp; SUM(SAL) ---------- 29025 PPAS scott=# select SUM(sal) from emp; sum ---------- 29025.00 (1 row) 2查询出公司的最高工资,最低工资,平均工资 Oracle SQL> select AVG(sal),ROUND(AVG(sal),2),MAX(sal),MIN(sal) fro

MySql按周/月/日分组统计数据的方法

知识关键词:DATE_FORMAT select DATE_FORMAT(create_time,'%Y%u') weeks,count(caseid) count from tc_case group by weeks; select DATE_FORMAT(create_time,'%Y%m%d') days,count(caseid) count from tc_case group by days; select DATE_FORMAT(create_time,'%Y%m') month

分组统计查询(章节摘要)

1,在SQL中主要提供了5种分组函数,分别是COUNT(),AVG(),SUM(),MIN(),MAX()函数. 2,使用GROUP BY字句可以对数据进行分组操作,而使用HAVING字句可以对分组之后的数据进行再次过滤. 3,在分组时可以同时制定多个分组字段. 4,分组操作不仅可以用于实体表,也可以针对查询的临时表进行分组. 5,分组函数允许嵌套,但是嵌套之后的分组查询中不能再出现任何字段,包括分组字段.分组统计查询(章节摘要)