对代码的疑问:如果输入的某个数大于1000000怎么办?
代码中有详细解释!但代码只适用于非负整数,有局限性。
本题目要求读入n个整数,要求用最少的比较次数,输出它们的最小值和次小值。例如,对于12 13 1 10 34 1这6个数,最小值为1,次小值
为10。
输入格式:
输入有两行。第一行为整数个数n(≤1 000 000),第二行给出n个以空格分隔的整数。
输出格式:
对每一组输入,在一行中输出最小值和次小值,中间以一个空格分隔,但行尾没有多余空格。如果输入数据不足两个,则输出“Invalid Input”。如果没有次小值,则输出“There is no second smallest element”。
输入样例:
6
12 13 1 10 34 1
输出样例:
1 10
思路:
Java的题能用输入输出流就尽量别用Scanner!
由于输入的数量n<=1000000,无论输入数据还是将输入的数据排序或比较,都有超时的陷阱,所以直接申请一个大数组,将输入的数据按照值对应的坐标放入数组中,这样就避免了排序或,直接从前往后寻找最大值和次小值就行了!
//输入输出能用输入输出就尽量不用Scanner
//类是动态加载的,eg:import java.io.*;不会影响效率,你的程序需要哪个类就会加载哪个类,但会加大class文件的大小
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
//BufferedReader比Scanner效率高不少!!!!
public class 最快求最小值和次小值{
public static void main(String[] args) throws NumberFormatException, IOException {
/*
* System.in的类型是InputStream,它代表的是键盘接受的输入,就是说键盘是数据源;
* System.in的类型可以归结为节点流、字节流、输入流;
* 接下来是InputStreamReader这个对象是处理流,字符流,输入流;
* */
/*
read方法
功能:读取单个字符。
返回:作为一个整数(其范围从 0 到 65535 (0x00-0xffff))读入的字符,如果已到达流末尾,则返回 -1
readLine方法
功能:读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
*/
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//parseInt是解析数字字符串
int n = Integer.parseInt(br.readLine());
if(n<2)
System.out.println("Invalid Input");
else {
String Str = br.readLine();//n<=1000000
String[] s = Str.split(" ");
int[] num = new int[1000000];//不用自动初始化为0,默认全是0
for(int i=0;i<n;i++){
//放在数组中等于从小到大排序
num[Integer.parseInt(s[i])]+=1;//如果输入的某个数大于1000000怎么办
}
int min1=-1,min2=-1,j=0;
for(int i=0;i<1000000;i++){
//6
//12 13 1 10 34 1
if(num[i]!=0&&j==1){//次小值
min2 = i;
break;
}
if(num[i]!=0&&j==0){//最小值
min1 = i;j=1;
}
}
if(min2==-1){
System.out.println("There is no second smallest element");
}
else {
System.out.println(min1+" "+min2);
}
}
}
}