您的位置:首页 > 其它

蓝桥杯:错误票据(排序)

2014-02-12 17:10 232 查看
  历届试题 错误票据  

时间限制:1.0s   内存限制:256.0MB

问题描述

某涉密单位下发了某种票据,并要在年终全部收回。

每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。

因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。

你的任务是通过编程,找出断号的ID和重号的ID。

假设断号不可能发生在最大和最小号。

输入格式

要求程序首先输入一个整数N(N<100)表示后面数据行数。

接着读入N行数据。

每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000),请注意行内和行末可能有多余的空格,你的程序需要能处理这些空格。

每个整数代表一个ID号。

输出格式

要求程序输出1行,含两个整数m n,用空格分隔。

其中,m表示断号ID,n表示重号ID

样例输入1

2

5 6 8 11 9 

10 12 9

样例输出1

7 9

样例输入2

6

164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196

172 189 127 107 112 192 103 131 133 169 158 

128 102 110 148 139 157 140 195 197

185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190

149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188

113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119

样例输出2

105 120

问题分析:

错误票据,这道题很简单,就是找出两个数据就OK了,用到的算法就是排序。

根据题目要求,首先要输入一个数字N,表示有多少行,接着要输入N行数据,其中包括空格。

我们这里用gets()函数来输入数据,gets()函数可以输入空格,当遇到回车时,它会自动将回车 ' \r ' ,转换为 ' \0 ' 存放在该行的最尾部。

具体如下:

输入:612_34__5__\r    (ps:' _ '表示空格,' \r '表示回车)

存储:612_34__5__\0

好了,数据存好了,可是却是字符串型的,怎么比较大小呢?这里我们需要将字符串里面的每个数字提取出来。

提取时只要注意进位就行了。

比如:提取上面例子里面的612的时候。具体如下:(随便写的,具体提取还要考虑空格什嘛的,这里只是说明一下进位)

int data = 0;

while (1)

{

       data = data * 10 + str[i];    //注意这里的data进位

       ++i;

}

现在数据也有了,接着我们将保存好的数据从小到大排序,这样才方便后面的断号和重复ID的抓出来嘛。

排序的方法有很多,当初我们学C语言的时候学了冒泡,嘻嘻,我也就只有这种方法最熟练,手到擒来。

排序OK了,就是找ID了。我们看下面一段数据:

数据data[i]:5 6 8 9 9 10 11 12

很容易看出来吧,我们可以得出如下结论:

1.如果(data[i] + 2 == data[i+1]),则说明data[i]+1这个数据没有。m = data[i]+1,我们又把它保存下来。

2.如果(data[i] == data[i+1]  ),则说明data[i]数据重复了。n = data[i];我们把它保存下来。

当然了,为了节约时间,当着两个数据都找到之后,我们就跳出循环来,不再找后面的数据(题目说了只有一个ID有问题嘛)。

ps:这里需要注意的就是定义数组的时候,数组大小的问题。

注意题目中的一句话:“每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000),请注意行内和行末可能有多余的空格,你的程序需要能处理这些空格。”

我们这里用字符串存储:

char data[100][100 * 6 + 1000];

其中第一个100表示:最少一百行。后面的100 * 6 + 10000 ,100表示每行最少有一百个数字, 6 表示每个正整数最多占六位(不大于100000),后面的+1000是表示,给行额外增加的空间,因为在输入的时候不只要输入数据,题目说了还要输入空格。

(不过令人蛋疼的是,我这样定义char data[100][100]  也给我100分,不知道系统怎么搞的额。)

最后还有一个问题,我百撕不得其姐。

就是下面这两行代码。当我将第二行代码(即:getchar()),替换成fflush(stdin);时,AC竟然给我0分。

scanf("%d",&N);  //输入行数 
getchar();    //吸收回车

好了,就扯到这里了。放代码,如下。

附录:(错误票据:全部代码)

/*
Name: 蓝桥杯:错误票据
Copyright: 供交流
Author: Jopus
Date: 12/02/14 14:10
Description: dev-cpp 5.5.3
*/
#include <stdio.h>
int main()
{
int i = 0, j = 0, N = 0,len = 0,t = 0;
int m = 0, n = 0, k = 0;
char strData[100][100*6+1000];
int nData[10001] = {0};
scanf("%d",&N);           //输入行数
getchar();                //吸收回车
for (i = 0; i < N; ++i)
gets(strData[i]);     //输入N行数据
//将字符数据转化为int数组里面存放
for (i = 0; i < N; ++i)
{
j = 0;
while (strData[i][j] != '\0')     //一直搜索到每一行的末尾
{
if (strData[i][j] != ' ')     //如果为数据
nData[k] = nData[k] * 10 + (strData[i][j] - '0'); //进位
else if (j>0 && strData[i][j-1] != ' ' && strData[i][j] == ' ')//当录入完一个数据,++k
++k;
++j;
}
if (strData[i][j-1] != ' ')       //如果行末尾不是以空格结尾,而是直接回车。如:"32 123\0"
++k;
}
len = k;     //nData[] len = 数组长度
//将nData[]数组排序
for (i = 1; i < len; ++i)
for (j = 0; j < len-1; ++j)
{
if (nData[j] > nData[j+1])
{
t = nData[j];
nData[j] = nData[j+1];
nData[j+1] = t;
}
}
//	for (i = 0; i < len; ++i)
//		printf("%d ",nData[i]);
//	printf("\n");
//找重复和缺失数据
for (i = 0; i < len-1; ++i)
{
if (nData[i] == nData[i+1])  //重复
n = nData[i];
if (nData[i]+2 == nData[i+1])                              //缺失
m = nData[i]+1;
if (m != 0 && n != 0)             //当全部找到时,跳出循环
break;
}
printf("%d %d",m,n);
return 0;
}


提交序号姓名试题名称提交时间 


代码长度语言
C
C++
JAVA
评测结果
正确
错误
编译出错
运行错误
运行超时
内存超限
得分
100
1~99
0
CPU使用 


内存使用 


评测详情
67045Jopus错误票据02-12 16:301.566KBC正确1000ms976.0KB评测详情

转载请保留原文地址:http://blog.csdn.net/jopus/article/details/19122993

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息