zoukankan      html  css  js  c++  java
  • 问题 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
    ", 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
    ", 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("}
    ");
    			}	
    		}	
    	}
    	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("}
    ");
                }
            }
        }
    
    
    
    #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;
    }
    
  • 相关阅读:
    2015年校园招聘之腾讯(数据挖掘)笔试面试题目
    VBoxGuestAdditions.iso下载地址
    软件測试自学指南---从入门到精通
    C语言指针的初始化和赋值
    使用Jquery+EasyUI 进行框架项目开发案例解说之二---用户管理源代码分享
    完美攻略心得之圣魔大战3(Castle Fantisia)艾伦希亚战记(艾伦西亚战记)包含重做版(即新艾伦希亚战记)
    DatabaseMetaData的用法(转)
    Thread-safety with regular expressions in Java
    大象,大象
    使用 Java 实现 Comet 风格的 Web 应用
  • 原文地址:https://www.cnblogs.com/lingr7/p/9536396.html
Copyright © 2011-2022 走看看