先给出一道题,测试平台是Acwing, 这道题是腾讯2019年春招提前批笔试第二题。题目不难,但是如果不注意细节,很容易TLE(超时)
下面的做法是用JAVA scanner依次读入输入数据,但这样做的效率较低,会直接导致TLE:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner in = new Scanner(System.in); 6 int n = in.nextInt(); 7 for(int i = 1; i <= n; i++){ 8 int l = in.nextInt(); 9 int r = in.nextInt();10 11 int sum1 = 0;12 int sum2 = 0;13 if(r%2 == 0)14 sum1 = r/2;15 else16 sum1 = r/2-r;17 if((l-1)%2==0)18 sum2 = l/2;19 else20 sum2 = l/2-l;21 22 System.out.println(sum1-sum2);23 }24 }25 }
结果如下所示,在读入超过10万行的输入的时候直接超时
好的做法是使用BufferedReader来读输入,以下代码AC
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 5 6 public class Main { 7 8 9 public static void main(String[] args) throws IOException {10 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));11 int q = Integer.valueOf(br.readLine());12 while (q-- > 0) {13 String[] parts = br.readLine().split(" ");14 int l = Integer.valueOf(parts[0]);15 int r = Integer.valueOf(parts[1]);16 17 int k = (r-l+1)/2;18 int res = 0;19 if(l%2==0)20 res = -k;21 else22 res = k;23 if((r-l+1)%2==1){24 if(r%2==0)25 res += r;26 else27 res -=r;28 }29 System.out.println(res);30 }31 }32 }
代码通过:
可能有人觉得Scanner我也可以使用整行读入的方式呀,可是这样仍然会TLE:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner in = new Scanner(System.in); 6 int n = in.nextInt();//Scanner读入一个int后, 读入指针仍然停留在该行 7 in.nextLine();//必须消耗掉上一行的所有数据,读到\n,才能去读下一行,因此这里用nextLine()消耗掉上一行的末尾 8 for(int i = 1; i <= n; i++){ 9 String[] parts = in.nextLine().split(" ");10 int l = Integer.valueOf(parts[0]);11 int r = Integer.valueOf(parts[1]);12 13 14 int k = (r-l+1)/2;15 int res = 0;16 if(l%2==0)17 res = -k;18 else19 res = k;20 if((r-l+1)%2==1){21 if(r%2==0)22 res += r;23 else24 res -=r;25 }26 System.out.println(res);27 }28 }29 }
说明Scanner在读入大量数据的时候确实不如BufferedReader的效率高!
有人作了测试:
BufferedReader可以用来读取文件或者接收来自键盘(控制台)的信息。它比Scanner更加快捷,能够大幅度缩短程序运行时间。它下面的readline()方法可以一次性读取一行文字(String),非常方便。需要注意的是,使用BufferedReader对象的readLine()方法必须处理java.io.IOException异常(Exception)。以及,在使用完BufferredReader以后,需要用close()方法关闭流。
可以从源码上看看这两者之间的区别
这里面有点类似与,C++提供的cin输入流的效率远不如C的scanf函数效率高