引言
对于很多走java后端的小伙伴都避免不了用java去写算法题,而对于像力扣这种刷题网站不需要我们处理输入输出,我们就会写的很舒服,但是如果是洛谷,牛客,cf,各大高校的oj之类的刷题网站需要我们自己处理输入输出,我们就会意识到java那个Scanner类读取数据是非常慢的(当然java什么都比c++慢),我这里的慢是指可能读取数据就把那一秒时限给跑完了。
所以这里我给大家分享一个保姆级别的java快读类,让你就像在用scanner一样得心应手,但读入又快了不少,以至于不影响大佬你ac题的速度。下面进入正文。
我这里先贴模板了,再给出解释,因为我觉得可能很多人都是为了模板来的,hhh。
可以直接把下面这段代码贴你代码下面,然后就可以开始成为无情的刷题机器了。方法名和作用都和你之前用Scanner类是一样的。
class read {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(bf);
String next() {
return st.sval;
}
String nextLine() throws IOException {
return bf.readLine();
}
int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
long nextLong() throws IOException {
st.nextToken();
return (long) st.nval;
}
double nextDouble() throws IOException {
st.nextToken();
return st.nval;
}
}
相信看到这里的都是不知道为什么Scanner类慢,以及这个快读类快的同学了吧,下面我就给大家详细解释一下
首先我们来解释一下为什么Scanner类慢:
因为Scanner类的输入的信息都是放在一个文件里,Scanner每次调用next()都需要访问IO设备,而且每次调用都只会取出去一个数,所以这样的速度就非常的慢。
而为什么我们这个read类就快了,细心的你在看上面的代码是一定会发现,其实我们read类主要就是两个对象在起作用,一个是BufferedReader,另一个是StreamTokenizer。
首先是BufferedReader,详细大家对他都不陌生,在学习io流时就对他有所了解了,它读取数据时,会先把放在文件中的数据全部放到内存缓冲区去,BufferedReader.next()的时候就直接到内存缓冲区拿数据。
接着我们来介绍一下这个类StreamTokenizer。StreamTokenizer这类用于将输入流(比如文件或者字符串)分解为词法单元(tokens)。它可以识别不同类型的词法单元,如数字、字符串、标识符、运算符等,并将它们以相应的类型进行分类。在处理文本文件或解析简单的文本格式时,StreamTokenizer非常有用。也就是说StreamTokenizer类可以帮我们帮我转换当前读入是数字还是字符。
下面我就带大家来实践一下这个read类。就拿下面这道题来举例吧[NOIP2016 普及组] 海港 - 洛谷https://www.luogu.com.cn/problem/P2058 补充一句,一般对于输入大于十的五次方的题目,基本上用Scanner就过不了,但是其实我们一直用快读类就好了,直接忘掉Scanner吧。
这道题并不难,相信大家都会吧,同样我也不是来讲算法的,如果不会可以评论区留言,我也可以给你仔细讲一下。
对于这道题如果我们用Scanner来读取数据那代码就是下面这样。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.*;
public class Main {
private static int[] personNum = new int[1000005];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int ans = 0;
Queue<person> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
int t = sc.nextInt();
int k = sc.nextInt();
List<Integer> list = new ArrayList<>();
for (int j = 0; j < k; j++) {
int x = sc.nextInt();
list.add(x);
personNum[x]++;
if (personNum[x] == 1) ans++;
}
person p = new person(t, list);
while (!queue.isEmpty() && t - queue.peek().t >= 86400) {
for (Integer count : queue.peek().list) {
personNum[count]--;
if (personNum[count] == 0) ans--;
}
queue.poll();
}
queue.add(p);
System.out.println(ans);
}
}
}
class person {
public int t;
public List<Integer> list;
public person(int t, List<Integer> list) {
this.t = t;
this.list = list;
}
}
对比一下数据样例,我们当前这个算法的时间复杂度是绝对没有超的。但是当我们信心满满提交后,就会得到好几个mle,就好比下面这样。
但是如果我们用上面的read快读类,代码就像下面这样,其实差不了多少,这种快读模板,直接cv上去就好了。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class Main {
private static int[] personNum = new int[1000005];
public static void main(String[] args) throws Exception {
read rf = new read();
int n = rf.nextInt();
int ans = 0;
Queue<person> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
String[] split = rf.nextLine().split(" ");
int t = Integer.parseInt(split[0]);
int k = Integer.parseInt(split[1]);
List<Integer> list = new ArrayList<>();
for (int j = 0; j < k; j++) {
int x = Integer.parseInt(split[j + 2]);
list.add(x);
personNum[x]++;
if (personNum[x] == 1) ans++;
}
person p = new person(t, list);
while (!queue.isEmpty() && t - queue.peek().t >= 86400) {
for (Integer count : queue.peek().list) {
personNum[count]--;
if (personNum[count] == 0) ans--;
}
queue.poll();
}
queue.add(p);
System.out.println(ans);
}
}
}
class person {
public int t;
public List<Integer> list;
public person(int t, List<Integer> list) {
this.t = t;
this.list = list;
}
}
class read {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(bf);
String next() {
return st.sval;
}
String nextLine() throws IOException {
return bf.readLine();
}
int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
long nextLong() throws IOException {
st.nextToken();
return (long) st.nval;
}
double nextDouble() throws IOException {
st.nextToken();
return st.nval;
}
}
然后这时我们再来提交,就会喜提ac,
最后谢谢大家看到最后,制作不易,如果觉得还不错,可以三连支持一下。
关关难过关关过。
标签:Java,java,int,list,st,----,import,快读,new From: https://blog.csdn.net/2301_80339238/article/details/140217566