本题目要求读入n个整数,要求用最少的比较次数,输出它们的最大值、第2大的值和第3大的值。例如,对于13 13 1 10 34 10这6个数,最大值为34,第2大的值为13,第3大的值为10。
输入格式:
输入有两行。第一行为整数个数n(≤1 000 000),第二行给出n个以空格分隔的整数。
输出格式:
对每一组输入,在一行中输出最大值、第2大的值和第3大的值值,中间以一个空格分隔,但行尾没有多余空格。
如果输入数据不足三个,则输出“Invalid Input”。
如果没有第3大的值,则输出“There is no third largest element”。
如果没有第2大和第3大的值,则输出“There is no second largest and third largest element”。
输入样例:
6
13 13 1 10 34 10
输出样例:
34 13 10
一点分析:
这道题的数据量,可见庞大。一般的排序方法并不凑效(类似于冒泡算法的这种),所以这里的排序,用的是一种最“手把手”的方法。就是把输入的数字不断地与最大的数字进行比较,有点类似于线性表的插入操作。废话不多说,直接上代码。
#include<stdio.h>
#define Max 10000000 //先来个宏定义,为什么数值是10000000,下面就解释
int main()
{
long long int n; //因为题目说了要将n个整数进行比较,但是并没有说是正整数
long long int t,i; //但是为什么要初始化为一个很小的负数呢?
long long int med=-Max,min=-Max; //想象一个场景,如果是直接int max的话,max默认为0
long long int max=-Max; //现在输入的数全部是负数,判断负数比0小,那么这个程序就失去正确性了
//虽然这题是AC了,但是后来仔细一想,其实还是有漏洞的,如果输入的数字比-10000000还小呢
scanf("%lld",&n);
if(n<3)
{
printf("Invalid Input");
return 0;
}
for(i=0;i<=n-1;i++) //现在开始输入数字
{
scanf("%lld",&t);//每次输入一个数字
if(t>max&&t!=max&&t!=min&&t!=med)//首先先与最大的数字进行比较
{
min=med; //这整个过程我称它为插入操作
med=max; //相当于t->max->med->min
max=t; //赋值的顺序一定不能乱
continue;
}
if(t>med&&t!=max&&t!=min&&t!=med) //一系列数中,可能会有相同数字
{
min=med; //赋值的顺序同样不能乱
med=t;
continue;
}
if(t>min&&t!=max&&t!=min&&t!=med)
{
min=t;
continue;
}
}
if(min==med&&min==-Max) //这种情况会出现在所有数都一样的情况下
{
printf("There is no second largest and third largest element");
return 0;
}
if(min==-Max) //一般情况,没有第三大的数字
{
printf("There is no third largest element");
return 0;
}
if(med==-Max)//一般情况,没有第二和第三大的数字
{
printf("There is no second largest and third largest element");
return 0;
}
printf("%lld %lld %lld",max,med,min);
return 0;
}