zoukankan      html  css  js  c++  java
  • Scanner和BufferReader的效率问题

    先给出一道题,测试平台是Acwing, 这道题是腾讯2019年春招提前批笔试第二题。题目不难,但是如果不注意细节,很容易TLE(超时)

    https://www.acwing.com/problem/content/570/

    下面的做法是用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 else
    16 sum1 = r/2-r;
    17 if((l-1)%2==0)
    18 sum2 = l/2;
    19 else
    20 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 else
    22 res = k;
    23 if((r-l+1)%2==1){
    24 if(r%2==0)
    25 res += r;
    26 else
    27 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();//必须消耗掉上一行的所有数据,读到
    ,才能去读下一行,因此这里用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 else
    19 res = k;
    20 if((r-l+1)%2==1){
    21 if(r%2==0)
    22 res += r;
    23 else
    24 res -=r;
    25 }
    26 System.out.println(res);
    27 }
    28 }
    29 }

     说明Scanner在读入大量数据的时候确实不如BufferedReader的效率高!

    有人作了测试:

    从测试结果来看,Scanner的平均耗时是BufferedReader的10倍左右.

    在这里贴上关于Scanner和BufferedReader的对比分析。

    BufferedReader可以用来读取文件或者接收来自键盘(控制台)的信息。它比Scanner更加快捷,能够大幅度缩短程序运行时间。它下面的readline()方法可以一次性读取一行文字(String),非常方便。需要注意的是,使用BufferedReader对象的readLine()方法必须处理java.io.IOException异常(Exception)。以及,在使用完BufferredReader以后,需要用close()方法关闭流

     这篇博客也讨论了这个问题

    可以从源码上看看这两者之间的区别

    【Java8源码分析】IO包-Reader、BufferedReader和Scanner总结

    这里面有点类似与,C++提供的cin输入流的效率远不如C的scanf函数效率高

    TALK IS CHEAP, SHOW ME THE CODE
  • 相关阅读:
    R
    P
    O
    M
    二分算法的一些思考
    I
    H
    G
    5-46 新浪微博热门话题 (30分)——unfinished HASH
    BZOJ 1179: [Apio2009]Atm
  • 原文地址:https://www.cnblogs.com/greatLong/p/10658267.html
Copyright © 2011-2022 走看看