每日一题 清点代码库

code.jpg

上图转自新浪微博:“阿里代码库有几亿行代码,但其中有很多功能重复的代码,比如单单快排就被重写了几百遍。请设计一个程序,能够将代码库中所有功能重复的代码找出。各位大佬有啥想法,我当时就懵了,然后就挂了。。。”

这里我们把问题简化一下:首先假设两个功能模块如果接受同样的输入,总是给出同样的输出,则它们就是功能重复的;其次我们把每个模块的输出都简化为一个整数(在 int 范围内)。于是我们可以设计一系列输入,检查所有功能模块的对应输出,从而查出功能重复的代码。你的任务就是设计并实现这个简化问题的解决方案。

输入格式:

输入在第一行中给出 2 个正整数,依次为 N(≤104)和 M(≤102),对应功能模块的个数和系列测试输入的个数。

随后 N 行,每行给出一个功能模块的 M 个对应输出,数字间以空格分隔。

输出格式:

首先在第一行输出不同功能的个数 K。随后 K 行,每行给出具有这个功能的模块的个数,以及这个功能的对应输出。数字间以 1 个空格分隔,行首尾不得有多余空格。输出首先按模块个数非递增顺序,如果有并列,则按输出序列的递增序给出。

注:所谓数列 { A1​, ..., AM​ } 比 { B1​, ..., BM​ } 大,是指存在 1≤i<M,使得 A1​=B1​,...,Ai​=Bi​ 成立,且 Ai+1​>Bi+1​。

输入样例:

7 3
35 28 74
-1 -1 22
28 74 35
-1 -1 22
11 66 0
35 28 74
35 28 74

输出样例:

4
3 35 28 74
2 -1 -1 22
1 11 66 0
1 28 74 35

题目虽长,实际意思非常简单,简单来说就是读入一段数据,然后统计这一段数据出现的次数,然然后按照出现次数的降序进行排序,然后这里特别说明一下并列的时候的情况。我们就拿题目给出的样例  1 11 66 0    1 28 74 35   他们出现的次数都是一次,并列了,但是为什么11 66 0会排在28 74 35的前面,那是因为根据数中的升序 11<28所以 28 74 35会排列在11 66 0的前面。好的现在我们已经理解题目的意思了 来讲讲题目的思路:

首先看到要统计出现的次数,我们会非常容易的想到用map,用map的key来储存那段数据,value来储存出现的次数 ,然后现在的问题就是这一段数据我们需要用什么储存,一开始我想使用string来当key记录这段数据,因为这样会方便很多,但是当我写完之后,我发现如果出现并列的情况,string这段数据(但是这样可以拿到18分 有两个测试点拿不到)并不好判断哪个在前面哪个在后面(举个例子:754 9 5 和99 8 1 那这样排序的时候string会把754那一串排在前面因为(7<9)这样就错了) 所以这里我们只能使用vector来当key :

map<vector<int> ,int> c;

然后把数据放进去,注意在为空的时候要初始化一下:

int n,x,a;
	cin>>n>>x;
	map<vector<int> ,int> c;
	vector<int> temp;//临时vector读取
	for(int i = 0;i<n;i++){
		for(int j = 0;j<x;j++){
			cin>>a;
			temp.push_back(a);
		}
		if(c.count(temp)==0) c[temp] = 1;//判断是不是存在,不存在就初始化一下
		else c[temp]++;
		temp.clear();//用完临时数组要记得清空
	}

好,现在我们已经把所有的数据他们出现的次数都已经存起来了,这时候就要进行排序,但是sort排序在vector并不适用,所以我们这里需要把map转化为vector,在利用sort进行排序:

vector<pair<vector<int> ,int>> re(c.begin(),c.end());

写出比较器:先利用value排序。如果value相等就在利用key排序,这里的key是vector在里边他会自动取出vector的值一个一个来进行判断:

bool cmp(pair<vector<int> ,int> a,pair<vector<int> ,int> b){
		if(a.second!=b.second) return a.second>b.second;
		else return a.first<b.first;
}

排序:

	sort(re.begin(),re.end(),cmp);

然后再输出的时候要注意因为re的key是vector,不可以直接用re.first进行直接访问,需要开一个临时vector来存储这个key,再给他输出出来:

	vector<int> temp2;
    cout<<re.size()<<endl;
	for(int i = 0;i<re.size();i++){
		cout<<re[i].second;
		temp2 = re[i].first;
		for(int j = 0;j<temp2.size();j++) cout<<" "<<temp2[j];
		temp2.clear();
		cout<<endl;
		
	}

整体完成代码:

#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<vector<int> ,int> a,pair<vector<int> ,int> b){
		if(a.second!=b.second) return a.second>b.second;
		else return a.first<b.first;
}
int main()
{
	int n,x,a;
	cin>>n>>x;
	map<vector<int> ,int> c;
	vector<int> temp;
	for(int i = 0;i<n;i++){
		for(int j = 0;j<x;j++){
			cin>>a;
			temp.push_back(a);
		}
		if(c.count(temp)==0) c[temp] = 1;
		else c[temp]++;
		temp.clear();
	}
	vector<pair<vector<int> ,int>> re(c.begin(),c.end());
	sort(re.begin(),re.end(),cmp);
	vector<int> temp2;
    cout<<re.size()<<endl;
	for(int i = 0;i<re.size();i++){
		cout<<re[i].second;
		temp2 = re[i].first;
		for(int j = 0;j<temp2.size();j++) cout<<" "<<temp2[j];
		temp2.clear();
		cout<<endl;
		
	}
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值