先给出一道题, 测试平台是 Acwing, 这道题是腾讯 2019 年春招提前批笔试第二题. 题目不难, 但是如果不注意细节, 很容易 TLE(超时)
https://www.acwing.com/problem/content/570/
下面的做法是用 JAVA scanner 依次读入输入数据, 但这样做的效率较低, 会直接导致 TLE:
- import java.util.Scanner;
- public class Main {
- public static void main(String[] args) {
- Scanner in = new Scanner(System.in);
- int n = in.nextInt();
- for(int i = 1; i <= n; i++){
- int l = in.nextInt();
- int r = in.nextInt();
- int sum1 = 0;
- int sum2 = 0;
- if(r%2 == 0)
- sum1 = r/2;
- else
- sum1 = r/2-r;
- if((l-1)%2==0)
- sum2 = l/2;
- else
- sum2 = l/2-l;
- System.out.println(sum1-sum2);
- }
- }
- }
结果如下所示, 在读入超过 10 万行的输入的时候直接超时
好的做法是使用 BufferedReader 来读输入, 以下代码 AC
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- public class Main {
- public static void main(String[] args) throws IOException {
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- int q = Integer.valueOf(br.readLine());
- while (q--> 0) {
- String[] parts = br.readLine().split(" ");
- int l = Integer.valueOf(parts[0]);
- int r = Integer.valueOf(parts[1]);
- int k = (r-l+1)/2;
- int res = 0;
- if(l%2==0)
- res = -k;
- else
- res = k;
- if((r-l+1)%2==1){
- if(r%2==0)
- res += r;
- else
- res -=r;
- }
- System.out.println(res);
- }
- }
- }
代码通过:
可能有人觉得 Scanner 我也可以使用整行读入的方式呀, 可是这样仍然会 TLE:
- import java.util.Scanner;
- public class Main {
- public static void main(String[] args) {
- Scanner in = new Scanner(System.in);
- int n = in.nextInt();//Scanner 读入一个 int 后, 读入指针仍然停留在该行
- in.nextLine();// 必须消耗掉上一行的所有数据, 读到 \ n, 才能去读下一行, 因此这里用 nextLine()消耗掉上一行的末尾
- for(int i = 1; i <= n; i++){
- String[] parts = in.nextLine().split(" ");
- int l = Integer.valueOf(parts[0]);
- int r = Integer.valueOf(parts[1]);
- int k = (r-l+1)/2;
- int res = 0;
- if(l%2==0)
- res = -k;
- else
- res = k;
- if((r-l+1)%2==1){
- if(r%2==0)
- res += r;
- else
- res -=r;
- }
- System.out.println(res);
- }
- }
- }
说明 Scanner 在读入大量数据的时候确实不如 BufferedReader 的效率高!
有人作了测试:
从测试结果来看, Scanner 的平均耗时是 BufferedReader 的 10 倍左右.
在这里贴上关于 Scanner 和 BufferedReader 的对比分析. https://www.cnblogs.com/wennian/p/5036888.html
BufferedReader 可以用来读取文件或者接收来自键盘 (控制台) 的信息. 它比 Scanner 更加快捷, 能够大幅度缩短程序运行时间. 它下面的 readline()方法可以一次性读取一行文字 (String), 非常方便. 需要注意的是, 使用 BufferedReader 对象的 readLine() 方法必须处理 java.io.IOException 异常 (Exception). 以及, 在使用完 BufferredReader 以后, 需要用 close() 方法关闭流.
这篇博客也讨论了这个问题
可以从源码上看看这两者之间的区别
[Java8 源码分析] IO 包 - Reader,BufferedReader 和 Scanner 总结
这里面有点类似与, C++ 提供的 cin 输入流的效率远不如 C 的 scanf 函数效率高
来源: http://www.bubuko.com/infodetail-3011908.html