题目链接
题目背景
某涉密单位下发了某种票据,并要在年终全部收回。
题目描述
每张票据有唯一的 ID 号,全年所有票据的 ID 号是连续的,但 ID 的开始数码是随机选定的。因为工作人员疏忽,在录入 ID 号的时候发生了一处错误,造成了某个 ID 断号,另外一个 ID 重号。
你的任务是通过编程,找出断号的 ID 和重号的 ID。
数据保证断号不可能发生在最大和最小号。
输入格式
一个整数 N(N<100) 表示后面数据行数,接着读入 N 行数据,每行数据长度不等,是用空格分开的若干个(不大于 100 个)正整数(不大于 105),每个整数代表一个 ID 号。
输出格式
要求程序首先输入1行,含俩个整数m,n,用空格分隔,其中,m表示断号ID,n表示重号ID。
输入输出样例
sample #1
输入
2
5 6 8 11 9
10 12 9
输出
7 9
sample #2
输入
2
5 6 8 11 9
10 12 9
输出
7 9
解题思路
题目的意思就是将n行数进行字进行排序来查找出段号ID,和重号ID,题目保证段号不发生在最大号和最小号。常规思路就是将n行数排序好再从小到大寻找断号和重号ID。
数据范围:n(<=100)行,每行不多于 100个,ID不大于105。
最优思路(桶排序)
看见数据范围都比较小,只有105的大小,查找这个数是否出现或者出现多次,用桶排序进行最好。
看见题目有n行,在c里面可以用scanf()!=EOF来表示没读入文件末尾,对桶排序来说基本上相当于无用数据,所以直接读入就行。
桶排序后,开始遍历最小ID到最大ID进行判断,如果i为断层则,a[i]=0,i为重数的话,a[i]>1;
下面是ac的代码:
#include<iostream>
#include<string.h>
const int N=1e5+5;
int a[N],n,_;
int min=2*N,max=0;//最大最小值定义一定要记得给好初始化
void solve() {
std::cin>>n;//读入n行
while(std::cin>>_) {//在c++里面读到末尾就会结束
a[_]++;//桶排序
max=std::max(_,max);//求所有数的最大值,最大值函数
min=std::min(_,min);//求所有数的最小值,最小值函数
}
int duan,chong;//求断数,重数
for(int i=min; i<=max; ++i) {//遍历区间
if(a[i]==0) duan=i;//找断数
if(a[i]>1) chong=i;//找重数
}
std::cout<<duan<<" "<<chong;//输出
}
int main() {
//快速读入
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
solve();
return 0;
}
普通排序求解(o(n2)会超时,记得用排序函数)
普通做法就是排好序,把数组遍历一次就行。题目保证断数不在开头结尾如果一个数是断层的那么a[i]-a[i-1]=2;a[i]-1为断数;重数就 是 a[i]=a[i-1];
思路就是这样,下面是代码:
#include<iostream>
#include<algorithm>
const int N=1e5+5;
int n,a[N],cnt,duan,chong,t;
void solve(){
std::cin>>n;
while(std::cin>>t){
a[cnt++]=t;
}
std::sort(a,a+cnt);//自带的排序
for(int i=1;i<cnt;++i){
if(a[i]-a[i-1]>1) duan=a[i]-1;
if(a[i]==a[i-1]) chong=a[i];
}
std::cout<<duan<<" "<<chong;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
solve();
return 0;
}
GOOD LUCK! HAVE FUN!