蓝桥杯C++——试题 历届试题 错误票据

蓝桥杯试题集试题总汇(C++)

问题描述

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

每张票据有唯一的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

分析

这道题的思路不难,无非将输入的数进行排序,利用一个循环找出重复的数和缺少的数。

这道题的考点在输入格式上,比赛输入都是文件输入的,文件中如果读取完了之后,它是会有一个结束标记EOF的,所以我们直接用while(cin >> x) 或者while(scanf("%d", &x) != EOF)就可以读完,还可以用freopen("in.txt","r",stdin)。如果下面这段代码就能通过测试,但个方法的弊端,是我们无法去测试我们的代码运行的正确性了,因为我们所写的输入语句,在自己的电脑上将是个死循环。

下面是按cin>>x形式输入的数据,可以通过蓝桥杯平台的测试。

//代码1
#include<iostream>
#include<algorithm>
using namespace std;
int a[10005];
int main()
{
    int n;
    cin>>n;//这里n就没有用了,后面直接输入数字
    int i=0;
    while(cin>>a[i])//这里他会提取文件中所有的输入数据,但真正在自己电脑上运行,这一步就会造成输入的死循环
        i++;
    sort(a,a+i);
    int ans1=0, ans2=0;//用于记录断掉的数字和重复的数字
    for(int j=0;j<i-1;j++)//"假设断号不可能发生在最大和最小号",这句话很重要
    {
        if(ans1 && ans2)
            break;
        if(a[j]==a[j+1]-1)
            continue;
        else if(a[j]==a[j+1])
            ans2=a[j];
        else
            ans1=a[j] + 1;
    }
    cout <<ans1<<" "<<ans2;
    return 0;
}

如果按“老实人”的思路,我们又该如何编写输入部分的代码呢?参考代码如下,但气人的事情来了,这个在自己电脑上输入输出完全正确,我甚至下载了蓝桥杯测试文件的输入输出数据,自己测试完全正确,但提交上去就是运行超时,你说气人不气人。

//代码2
#include <iostream>
#include<stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int a[10005];
int main()
{
	int n;
	cin>>n;
	int k=0;//记录有多少ID
	char ch=' ';
	int i,j=0,t;
	for( i=0;i<n;i++)
	{
		while(ch!='\n')
		{
			cin>>t;
			ch=getchar();//getchar()函数从键盘上读入一个字符,并显示该字符(回显)
			             //【敲什么键盘上就会显示什么】,但只有第一个字符作为函数的返回值。
			a[j++]=t;//将输入的数字,存在数组a中
			k++;
		}
		ch=' ';
	}
	sort(a,a+k);
	int ans1=0, ans2=0;//用于记录断掉的数字和重复的数字
    for(j=0;j<k-1;j++)//"假设断号不可能发生在最大和最小号",这句话很重要
    {
        if(ans1 && ans2)
            break;
        if(a[j]==a[j+1]-1)
            continue;
        else if(a[j]==a[j+1])
            ans2=a[j];
        else
            ans1=a[j] + 1;
    }
    cout <<ans1<<" "<<ans2;
	return 0;
}

接着从各大csdn的大佬中找寻新的方法,一位大佬用到了我一直没见过的函数——strtok,我改写了一下大佬的代码如下,很好的解决了输入数据的问题,也顺利的通过了蓝桥杯测试。如果你对strtok函数不清楚的话,可以参考网址

https://blog.csdn.net/dan15188387481/article/details/50511699

//代码3
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int ans[10005];
char str[100001];
int main()
{
    int n;
    cin>>n;
    int i,k=0;
    getchar();
    for(i=0; i<n; i++)
    {
        gets(str);
        char *p;
        p=strtok(str," ");
        ans[k++]=atoi(p);
        while(p)
        {
            p=strtok(NULL," ");
            if(p)
                ans[k++]=atoi(p);
        }
    }
    sort(ans,ans+k);
    int ans1,ans2;
    for(i=0; i<k-1; i++)
    {
        if(ans[i+1]-ans[i]==2)
        {
            ans1=ans[i]+1;
        }
        if(ans[i+1]==ans[i])
            ans2=ans[i];
    }
    cout<<ans1<<" "<<ans2;

}

当然这道题还有新的解题方法,我见有大佬利用了用分开字符流,提取输入数字的方法。还用Java代码中理由split库函数的处理的。但我粘贴了他们的代码,写的很好,但有点不能通过蓝桥杯测试,所以我就不分享了,大家可以自己多找找。总结下来,这个题还是很有考究的。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值