Java竞争性编程:Java快速I/O介绍

2021年4月7日18:24:09 发表评论 746 次浏览

许多人不建议在竞争性编程中使用Java, 因为它的输入和输出很慢, 而且确实很慢。

在本文中, 我们讨论了一些解决难题的方法, 详细介绍Java快速I/O,并将判决从TLE更改为(大多数情况下)AC。

对于以下所有程序

输入如下:

7 3
1
51
966369
7
9
999996
11

输出如下:

4

Scanner类–(简单, 打字少, 但不建议非常慢, 请参阅

这个(由于运行缓慢):在大多数情况下, 我们在使用扫描仪类时会获得TLE。它使用内置的nextInt(), nextLong(), nextDouble方法在使用输入流启动扫描器对象后读取所需的对象(例如System.in)。以下程序很多时候都超过了时间限制, 因此没有太大用处。

//Working program using Scanner
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main
{
     public static void main(String[] args)
     {
         Scanner s = new Scanner(System.in);
         int n = s.nextInt();
         int k = s.nextInt();
         int count = 0 ;
         while (n--> 0 )
         {
             int x = s.nextInt();
             if (x%k == 0 )
                count++;
         } 
         System.out.println(count);
     }
}

缓冲读取器 - Java的快速I/O

(快速, 但不建议这样做, 因为它需要大量键入操作):Java.io.BufferedReader类从字符输入流中读取文本, 缓冲字符, 以便有效读取字符, 数组和行。使用这种方法, 我们每次都必须解析所需类型的值。由于使用Stringtokenizer, 因此从单行读取多个单词会增加其复杂性, 因此不建议这样做。大约0.89 s的运行时间已被接受, 但仍然可以看到, 它需要很多次键入, 因此建议使用方法3。

//Working program using BufferedReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
  
public class Main
{
     public static void main(String[] args) throws IOException
     {
  
         BufferedReader br = new BufferedReader(
                               new InputStreamReader(System.in));
  
         StringTokenizer st = new StringTokenizer(br.readLine());
         int n = Integer.parseInt(st.nextToken());
         int k = Integer.parseInt(st.nextToken());
         int count = 0 ;
         while (n--> 0 )
         {
             int x = Integer.parseInt(br.readLine());
             if (x%k == 0 )
                count++;
         }
         System.out.println(count);
     }
}

Java的快速I/O - 用户定义的FastReader类

(使用bufferedReader和StringTokenizer):此方法利用BufferedReader和StringTokenizer的时间优势以及用户定义的方法的优势, 以减少键入次数, 从而加快输入速度。这将在1.23 s的时间内被接受, 并且此方法是

非常推荐

因为它容易记住, 并且速度足以满足竞争性编码中大多数问题的需求。

//Working program with FastReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
  
public class Main
{
     static class FastReader
     {
         BufferedReader br;
         StringTokenizer st;
  
         public FastReader()
         {
             br = new BufferedReader( new
                      InputStreamReader(System.in));
         }
  
         String next()
         {
             while (st == null || !st.hasMoreElements())
             {
                 try
                 {
                     st = new StringTokenizer(br.readLine());
                 }
                 catch (IOException  e)
                 {
                     e.printStackTrace();
                 }
             }
             return st.nextToken();
         }
  
         int nextInt()
         {
             return Integer.parseInt(next());
         }
  
         long nextLong()
         {
             return Long.parseLong(next());
         }
  
         double nextDouble()
         {
             return Double.parseDouble(next());
         }
  
         String nextLine()
         {
             String str = "" ;
             try
             {
                 str = br.readLine();
             }
             catch (IOException e)
             {
                 e.printStackTrace();
             }
             return str;
         }
     }
  
     public static void main(String[] args)
     {
         FastReader s= new FastReader();
         int n = s.nextInt();
         int k = s.nextInt();
         int count = 0 ;
         while (n--> 0 )
         {
             int x = s.nextInt();
             if (x%k == 0 )
                count++;
         }
         System.out.println(count);
     }
}

Java快速I/O - 使用Reader类:还有另一种快速解决问题的方法, 我想说是最快的方法, 但不建议这样做, 因为它在执行过程中需要非常麻烦的方法。它使用inputDataStream读取数据流, 并使用read()方法和nextInt()方法获取输入。到目前为止, 这是最快的输入方法, 但很难记住, 而且方法繁琐。下面是使用此方法的示例程序。

令人惊讶的时间仅为0.28 s, 这被接受。尽管这是非常快的, 但是显然这不是一个容易记住的方法。

//Working program using Reader Class
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
  
public class Main
{
     static class Reader
     {
         final private int BUFFER_SIZE = 1 <<16 ;
         private DataInputStream din;
         private byte [] buffer;
         private int bufferPointer, bytesRead;
  
         public Reader()
         {
             din = new DataInputStream(System.in);
             buffer = new byte [BUFFER_SIZE];
             bufferPointer = bytesRead = 0 ;
         }
  
         public Reader(String file_name) throws IOException
         {
             din = new DataInputStream( new FileInputStream(file_name));
             buffer = new byte [BUFFER_SIZE];
             bufferPointer = bytesRead = 0 ;
         }
  
         public String readLine() throws IOException
         {
             byte [] buf = new byte [ 64 ]; //line length
             int cnt = 0 , c;
             while ((c = read()) != - 1 )
             {
                 if (c == '\n' )
                     break ;
                 buf[cnt++] = ( byte ) c;
             }
             return new String(buf, 0 , cnt);
         }
  
         public int nextInt() throws IOException
         {
             int ret = 0 ;
             byte c = read();
             while (c <= ' ' )
                 c = read();
             boolean neg = (c == '-' );
             if (neg)
                 c = read();
             do
             {
                 ret = ret * 10 + c - '0' ;
             }  while ((c = read())>= '0' && c <= '9' );
  
             if (neg)
                 return -ret;
             return ret;
         }
  
         public long nextLong() throws IOException
         {
             long ret = 0 ;
             byte c = read();
             while (c <= ' ' )
                 c = read();
             boolean neg = (c == '-' );
             if (neg)
                 c = read();
             do {
                 ret = ret * 10 + c - '0' ;
             }
             while ((c = read())>= '0' && c <= '9' );
             if (neg)
                 return -ret;
             return ret;
         }
  
         public double nextDouble() throws IOException
         {
             double ret = 0 , div = 1 ;
             byte c = read();
             while (c <= ' ' )
                 c = read();
             boolean neg = (c == '-' );
             if (neg)
                 c = read();
  
             do {
                 ret = ret * 10 + c - '0' ;
             }
             while ((c = read())>= '0' && c <= '9' );
  
             if (c == '.' )
             {
                 while ((c = read())>= '0' && c <= '9' )
                 {
                     ret += (c - '0' ) /(div *= 10 );
                 }
             }
  
             if (neg)
                 return -ret;
             return ret;
         }
  
         private void fillBuffer() throws IOException
         {
             bytesRead = din.read(buffer, bufferPointer = 0 , BUFFER_SIZE);
             if (bytesRead == - 1 )
                 buffer[ 0 ] = - 1 ;
         }
  
         private byte read() throws IOException
         {
             if (bufferPointer == bytesRead)
                 fillBuffer();
             return buffer[bufferPointer++];
         }
  
         public void close() throws IOException
         {
             if (din == null )
                 return ;
             din.close();
         }
     }
  
     public static void main(String[] args) throws IOException
     {
         Reader s= new Reader();
         int n = s.nextInt();
         int k = s.nextInt();
         int count= 0 ;
         while (n--> 0 )
         {
             int x = s.nextInt();
             if (x%k == 0 )
                count++;
         }
         System.out.println(count);
     }
}

建议阅读:

巨大的输入测试 旨在检查你的语言的快速输入处理。SPOJ记录了所有程序的时间。

以上就是竞争性编程的Java快速I/O的全部内容,如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请发表评论。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: